我们都知道,nodejs是基于google的v8引擎的,v8引擎呢,是用C或者说C++写的,各种第三方模块(大多数)也是用C++写的,原因很简单,效率高,而且,很多第三方模块原本就有C++版本,只要用addons包装一下,就可以在nodejs中直接使用。我门何不开发一个自己的模块试试呢。
首先,需要安装node-gyp,它可以帮我们把C/C++的源码编译成nodejs认识的格式。
npm install -g node-gyp
有可能安装中会遇到问题,比如gcc等未安装,权限不够等等,这些基本问题,相信读者自己能搞定。
新建一个项目,目录结构如下(我用的webstorm),你也可以用自己熟悉的编辑器
项目下有node_modules目录,我们自定义的模块都放在下面,然后在node_modules目录下新建hello目录,在hello下新建hello.cc,内容如下
#include <stdio.h>
#include <stdlib.h>
#include <node.h>
#include <v8.h>
using namespace v8;
/**
* 输出world
*/
Handle<Value> hello(const Arguments& args)
{
HandleScope scope;
return scope.Close(String::New("world"));
}
void init(Handle<Object> exports) {
exports->Set(String::NewSymbol("hello"), FunctionTemplate::New(hello)->GetFunction());
}
NODE_MODULE(hello, init)
#include命令,相信大家都很熟悉(不熟悉的话,就去先学C/C++吧),v8最常用的两个头文件<node.h>和<v8.h>,有兴趣的同学可以去下载源码,自己去看看。
然后v8引擎的Value,Data,Object,Array,String等都在v8的名称空间下
using namespace v8;
声明使用v8名称空间。
void init(Handle<Object> exports) {
exports->Set(String::NewSymbol("hello"), FunctionTemplate::New(hello)->GetFunction());
}
NODE_MODULE(hello, init)
定义模块的入口函数及模块的名称,我们的入口函数叫init,模块名称叫hello,这个叫hello的模块,有一个叫hello的函数,它绑定的是hello这个函数
/**
* 输出world
*/
Handle<Value> hello(const Arguments& args)
{
HandleScope scope;
return scope.Close(String::New("world"));
}
然后编辑(新增)/node_modules/hello/binding.gyp文件,内容如下
{
"targets": [
{
"target_name": "hello",
"sources": [ "hello.cc"],
"include_dirs":[]
}
]
}
注意target_name必须和
NODE_MODULE(hello, init)
中的第一个参数一致。
然后在/node_modules/hello下执行
node-gyp configure build
输出如下
gyp info it worked if it ends with ok
gyp info using node-gyp@1.0.2
gyp info using node@0.10.30 | linux | x64
gyp info spawn python
gyp info spawn args [ '/usr/local/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args '/home/***/workspace/csdn/learn_nodejs/node_modules/hello/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args '/usr/local/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/home/***/.node-gyp/0.10.30/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/home/***/.node-gyp/0.10.30',
gyp info spawn args '-Dmodule_root_dir=/home/***/workspace/csdn/learn_nodejs/node_modules/hello',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.' ]
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
make: 进入目录“/home/***/workspace/csdn/learn_nodejs/node_modules/hello/build”
CXX(target) Release/obj.target/hello/hello.o
SOLINK_MODULE(target) Release/obj.target/hello.node
SOLINK_MODULE(target) Release/obj.target/hello.node: Finished
COPY Release/hello.node
make: 离开目录“/home/***/workspace/csdn/learn_nodejs/node_modules/hello/build”
gyp info ok
***是我的用户目录,我把它注释掉了,看最后一行,gyp和我们说ok,不出意外的话,它会在hello目录下生成build目录
/learn_nodejs/node_modules/hello/build/Release/hello.node
就是gyp为我们生成的目标文件,下面我们在js中使用它。
新建/learn_nodejs/node_modules/hello/test.js,内容如下
var module = require('./build/Release/hello');
var value = module.hello();
console.log(value);
执行test.js,输出如下
world
是不是很奇妙,C/C++就这样和nodejs完美的变成了一个整体。