深入浅出Node.js读书笔记:Node.js的c/c++扩展模块(2.4)

对于前端开发工程师来说,c/c++有些生疏或晦涩,但如果能够掌握,当模块出现性能瓶颈时,将对你有极大帮助。

Javascript的一个典型弱点是位运算。它的实现是参考Java的位运算实现,Java的位运算是通过Int类型进行比较,而Javascript只有double类型的数据,它需要先把double类型转换成int类型才能进行位运算比较。所以在Javascript层面进行位运算效率不高。

在应用中,会频繁出现位运算操作,例如编码,转码等逻辑,如果通过javascript实现,会耗费大量cpu。如果通过编写c/c++扩展模块,那么就能提升性能。

下面介绍c/c++扩展模块的编写,编译,加载和导出过程。

介绍之前,先明确,编写的c/c++代码最好是跨平台,通过*nix和windows上不同的编译工具,生成.node文件, 再通过process.dlopen加载该文件,从而实现不同平台加载c/c++模块。

2.4.1 前提条件

编写c++需要一定的功底,下面这些如果能够了解,可以让你在编写过程中事半功倍。

GYP项目生成工具。
是一个跨平台的项目生成器。即 “Generate Your Projects”的缩写。它可以帮你生成不同平台的项目文件。比如windows下的.sln,Mac下的Xcode等。

V8引擎c++库。
V8是Node自身动力来源。它自身是由c++实现,实现Javascript与c++的相互调用。

libuv库。
Node能够实现跨平台的原因就是使用了libuv库。这个库是跨平台,它底层封装了不同平台的实现。

Node内部库。
Node自身提供的c++代码,可以把它当作工具类来使用。

其他库。
在deps目录下存在zlib,openssl,http_parser等。

2.4.2 c/c++扩展模块的编写

Javascript原型代码如下:

  exports.sayHello = function(){
        return "Hello world";
  }

新建hello目录作为自己的项目目录,编写hello.cc并将其存储到src目录下,代码如下:

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

  using namespace v8;
  Handle<Value> SayHello(const Argument& args){
        HandleScope 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(hello,Init_Hello)

通过dlopen()来动态加载,然后导出给Javascript调用。

2.4.3 c/c++扩展模块的编译

在GYP工具帮助下,c/c++扩展模块的编译是一件省心的事,无须为每个平台编写不同的项目文件。具体内容如下:

 {
    'target':[
        {
        	'target_name':'hello',
        	'sources':[
        		'src/hello.cc'
            ],
            'conditions':[
            	['OS == "win"',
            		{
            			'libraries':['-lnode.lib']
					}
				]
			]
		}
    ]
}

然后调用:
$ node-gyp configure

该命令会在当前目录创建build目录,并生成系统相关的项目文件。

在*nix平台下,build目录中会出现makefile文件;在windows下,则会生成vcxproj等文件。

继续执行
$ node-gyp build

编译过程会根据不同平台,分别通过make或vcbuild进行编译。编译后hello.node文件会生成在build/Release目录下。

2.4.4 c/c++扩展模块的加载

得到hello.node后,通过执行如下代码就可以:

    var hello = require('./build/Release/hello.node');
    console.log(hello.sayHello());

c/c++扩展模块由于已经编译为.node文件(实际是.so或.dll文件),加载速度比javascript文件会快,这里其实是省略了文件的编译过程。

另外使用c/c++模块好处在于可以灵活动态地加载它们,保存Node模块自身简单性的同时,给予Node无限的扩展性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值