nan入门教程
Node.js在升级到0.12后,c++ API部分发生了翻天覆地的变化,如果你之前的代码是按照0.10的API编写的,将其改成0.12的形式是需要耗费一番精力的,但是问题又来了,你如果改为0.12形式,0.10又不能够被兼容了。幸好有nan,其实它的核心是一个头文件,通过宏定义来做不同版本的node的c++ API的兼容。
1.配置
首先你通过 npm install nan --save
来安装 nan ,然后在binding.gyp中配置:
"include_dirs" : [
"<!(node -e \"require('nan')\")"
]
最后在使用nan
的c++文件中引入头文件#include<nan.h>
。
2.demo
下面的demo摘自nan的readme文档
// addon.cc
#include <node.h>
#include <nan.h>
// ..引入async.h或者sync.h
using v8::FunctionTemplate;
using v8::Handle;
using v8::Object;
using v8::String;
void InitAll(Handle<Object> exports) {
exports->Set(NanNew<String>("calculateSync"),
NanNew<FunctionTemplate>(CalculateSync)->GetFunction());
exports->Set(NanNew<String>("calculateAsync"),
NanNew<FunctionTemplate>(CalculateAsync)->GetFunction());
}
NODE_MODULE(addon, InitAll)
代码2.1 addon.cc
首先就是导出函数部分,nan
中写法为exports->Set(NanNew<String>("calculateSync"), NanNew<FunctionTemplate>(CalculateSync)->GetFunction());
,对于c++ api来说,在nan中全部都要用NanNew
来声明,在0.10中这句话被写作exports->Set(String::NewSymbol("calculateSync"),FunctionTemplate::New(CalculateAsync)->GetFunction());
在0.12中是NODE_SET_METHOD(exports, "calculateSync", CalculateAsync);
。
正常情况下需要引入函数CalculateAsync
所在的头文件的,但是官方文档给出了两个CalculateAsync
函数的实现,一个同步版,一个异步版。同步版仅仅是直接调用:
// sync.h
#include <node.h>
#include <nan.h>
NAN_METHOD(CalculateSync);
代码2.2 sync.h
通过头文件就可以看出,函数声明的方式需要使用NAN_METHOD(CalculateSync)
,这等同于0.10中的Handle<Value> CalculateSync(const Arguments& args)
,在0.12中要这么写void CalculateSync(const FunctionCallbackInfo<Value>& args)
。
// sync.cc
#include <node.h>
#include <nan.h>
#include "./sync.h"
// ...引入第三方类库头文件
using v8::Number;
// Simple synchronous access to the `Estimate()` function
NAN_METHOD(CalculateSync) {
NanScope();
// expect a number as the first argument
int points = args[0]->Uint32Value();
double est = Estimate(points);//Estimate是一个第三方类库的函数,这里可以不用理会
NanReturnValue(NanNew<Number>(est));
}
代码2.3 sync.cc
首先是函数NanScope();
,他来完成node0.10中的HandleScope scope;
的功能,在node0.12中是:
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
函数结束返回值操作也变成由函数(确切的说应该是宏定义)NanReturnValue来代替。
更令人振奋的是,nan中还对libuv中的函数uv_queue_work
进行了抽象,可以通过继承类NanAsyncWorker
来实现异步话操作,省去了为了使用uv_queue_work
而自定义数据结构的步骤。下面就是async.cc的代码:
// async.cc
#include <node.h>
#include <nan.h>
#include "./async.h"
// ...引入第三方类库
using v8::Function;
using v8::Local;
using v8::Null;
using v8::Number;
using v8::Value;
class PiWorker : public NanAsyncWorker {
public:
PiWorker(NanCallback *callback, int points)
: NanAsyncWorker(callback), points(points) {}
~PiWorker() {}
//这个函数运行在工作线程,而不是v8线程,所以不能访问v8的数据
void Execute () {
estimate = Estimate(points);
}
//这个是libuv的回调函数,在这里可以使用v8的数据
void HandleOKCallback () {
NanScope();
Local<Value> argv[] = {
NanNull()
, NanNew<Number>(estimate)
};
callback->Call(2, argv);
};
private:
int points;
double estimate;
};
// Asynchronous access to the `Estimate()` function
NAN_METHOD(CalculateAsync) {
NanScope();
int points = args[0]->Uint32Value();
NanCallback *callback = new NanCallback(args[1].As<Function>());
NanAsyncQueueWorker(new PiWorker(callback, points));
NanReturnUndefined();
}
代码2.4 async.cc
这里有一个利用nan和node0.10/0.12来完成异步操作的对比。
这篇教程仅仅是一个入门操作,就讲到这里了,详细的使用请参考nan的readme文档。