NodeJS Addons 官方文档:http://nodejs.org/api/addons.html
Windows 下需要自己编译 Node 来得到 lib
因为 Node 使用 gyp 所以还需要 python 2.6 或 2.7 的环境,还要把 Visula Studio 安装好
NodeJS 编译很简单,花的时间也不长,下载源码包,使用里面的 vcbuild.bat 编译:
vcbuild.bat release
gyp 在 Windows 下编译时,会从注册表中得到 Visual Studio 的各个版本和目录,并自动选择一个来编译
编译后如果没有得到 node.lib ,那再编译一次就可以得到 node.lib
在编译 NodeJS Addons 时,需要使用 NodeJS 提供的工具来编译:node-gyp
node-gyp 在 deps\npm\bin\node-gyp-bin\ 目录下
代码写好后需要新建一个文件 binding.gyp 描述和配置这个模块,文件名必须是这个,内容如下:
{ "targets": [ { "target_name": "hello", "include_dirs": [ "mmseg" ], "msvs_settings": { "VCLinkerTool": { "AdditionalLibraryDirectories": [ "mmseg" ] } }, "sources": [ "hello.cpp" ] } ] }
这个文件中说明了模块名,代码文件,额外的头文件目录,额外的库目录
然后使用 node-gyp 生成项目文件并编译:
node-gyp configure build
如果同时安装了 VS2010 和 VS2012 那 gyp 会使用 VS2010 来编译
如果需要用 VS2012 编译,就只需 configure ,然后用 VS2012 打开项目文件自己编译
NodeJS Addons 的代码结构:
#pragma once #include <node.h> using namespace v8; class Hello : public node::ObjectWrap //继承于这个类会方便一些 { public: static void Init(Handle<Object> target); //导出对象时需要这个方法 private: Hello():m_count(0) {} ~Hello() {} static Handle<Value> New(const Arguments& args); //JS 中构造对象时,就调用这个方法 static Handle<Value> Test(const Arguments& args); //调用 JS 对象的 Test() 方法时,就调用这个函数 int m_count; //这是 C++ 对象中用的 };
实现代码:
#include <sstream> #include "Hello.h" using namespace std; void Hello::Init(Handle<Object> target) { //创建一个 JS 函数原型 Local<FunctionTemplate> tpl = FunctionTemplate::New(New); //JS 类型名称 tpl->SetClassName(String::NewSymbol("Hello")); tpl->InstanceTemplate()->SetInternalFieldCount(1); //一个成员方法 tpl->PrototypeTemplate()->Set( String::NewSymbol("test"), FunctionTemplate::New(Test)->GetFunction() ); //添加一个符号,并关联这个对象 target->Set( String::NewSymbol("Hello"), Persistent<Function>::New(tpl->GetFunction()) ); } Handle<Value> Hello::New(const Arguments& args) { HandleScope scope; //有 JS 的操作时,Scope 是必须有的 Hello* obj = new Hello(); //创建C++用的对象 obj->Wrap(args.This()); return args.This(); } Handle<Value> Hello::Test(const Arguments& args) { HandleScope scope; std::stringstream sout; Hello* self = ObjectWrap::Unwrap<Hello>(args.This()); sout<<"Hello["<<self->m_count++<<"]"; Local<String> result = String::New(sout.str().c_str()); return scope.Close(result); //返回字符串 } //导出 addons object void Init(Handle<Object> target) { //在这里导出对象,可以一次导出很多对象 Hello::Init(target); } NODE_MODULE(hello, Init)
在 Node 中使用:
var Addons = require('./hello'); var hello = new Addons.Hello(); console.log(hello.test());
V8 中的 String:可以使用 ASCII 或 UTF-8 的字符串构造 String,String 会自己判断并按格式去够着一个JS用的字符串。
V8 中有三个智能指针:Handle、Local、Persistent
Local 继承于 Handle ,改了构造函数,并添加了一个 New 方法,但和 Handle 没什么区别,需要和 HandleScope 一起使用
Persistent 则是持久性指针,可以在函数间传递对象,手动释放资源