深入浅出Node.js读书笔记:Node.js的核心模块(2.3)

之前提到,Node.js的核心模块会在编译Node的时候以二进制的方式被编译进来。核心模块分为c/c++和Javascript两部分。c/c++存在Node的src目录下,Javascript存在lib目录下。

2.3.1 Javascript核心模块编译过程

Node采用了V8附带的js2c.py工具 ,将内置的Javascript代码(src/node.js和lib/*.js)转换成c++数组,生成node_natives.h文件,在这个过程中Javascript代码以字符串的形式存储在Node命名空间中,是不可执行文件。在Node启动时,Javascript代码直接加载进内存中。

2.3.2 c/c++核心模块的编译过程

核心模块中,有一些模块是完全由c/c++实现,另一些模块的核心文件是由c/c++实现,另一部分是由Javascript封装。Node这种复合模式可以在开发速度和性能之间找到平衡点。

完全由c/c++编写的统一称为内建模块,它们不会被用户直接调用。Node的buffer,crypto,evals,fs,os等模块都是部分通过c/c++编写。

内建模块的优势在于:首先它们是由c++开发,性能优于脚本语言;其次,在进行文件编译时,它们被编译进二进制文件。一旦Node开始执行,它们被加载进内存中,无须再次做标识符,文件定位,编译等过程,直接就可执行。

Node所有模块类型中,存在着一种依赖关系,文件模块(Javascript)依赖核心模块,而核心模块(Javascript)依赖内建模块(c/c++)。

这里有个问题,内建模块如何把变量或者方法倒出,从而核心模块可以访问到呢?

Node在启动时,会生成一个全局变量process,并提供Binding()方法来协助加载内建模块。在加载内建模块时,先创建一个exports空对象,调用get_builtin_module()方法取出内建模块对象,通过执行register_func()填充exports对象,最后将exports对象按模块名缓存并返回给调用方完成导出。

该方法不仅可以倒出方法,还可以导出其他内容。

2.3.3 编写核心模块

以c/c++模块为例,演示如何编写内建模块。先编写一个极其简单的javascript版本原型,这个方法返回一个HelloWorld字符串:

	exports.sayHello = function(){
		return 'hello world';
	}

编写内置模块分为两部分,编写头文件和编写c/c++文件。

1.将如下代码保存为node_hello.h,存放到Node的src目录下:

	#ifndef NODE_HELLO_H_
	#define NODE_HELLO_H_
	
	#include<v8.h>
	
	namespace node {
		// 预定义方法
		v8::Handle<v8::Value> SayHello(const v8::Arguments& args);
	}
	
	#endif

2.编写node_hello.cc,并存储到src目录下:

	#include <node.h>
	#include <node_hello.h>
	#include <v8.h>

	namespace node {
		// 实现预定义方法
		Handle<Value> SayHello(const Arguments& args){
			HandleScopt scope;
			return scope.Close(String::New("hello world!"));
		}
	}

	// 给传入的目标对象添加sayHello方法
	void Init_Hello(Handle<Object> target){
		target->Set(String::NewSymbol("sayHello"),FunctionTemplate::New(SayHello)->GetFunction());
	}

	// 调用NODE_MODULE()将注册方法定义到内存中
	NODE_MODULE(node_hello,node::Init_Hello)

以上两部完成内建模块的编写,但是真正要让Node认为它是内建模块,还需要更改src/node_extension.h,在NODE_EXT_LIST_END前添加NODE_EXT_LIST_ITEM(node_hello),以将node_hello模块添加进node_module_list数组中。

另外还需要使得编译的代码编译进执行文件。同时还需要更改Node的项目生成文件node.gyp,并在’target_name’:'node’节点的sources中添加新编写的两个文件。

编译和安装后,直接node执行如下代码:

	var hello = process.binding('hello');
	hello.sayHello();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值