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 则是持久性指针,可以在函数间传递对象,手动释放资源