- Native Abstractions for Node.js (nan)
- nan方式的好处:使用nan方式,编写的c++插件接口,会自动兼容不同版本的nodejs
static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);
void hello(FunctionCallbackInfo<Value>& args);
Handle<Value> hello(const Arguments& args);
- 因此,你的代码只需要随着 nan版本升级出现的改变而改变,至于Nodejs,nan会帮你兼容(前提是nan支持该版本的nodejs)
Hello World
#include <nan.h>
void Method(const Nan::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(Nan::New("hello world").ToLocalChecked());
}
void Init(v8::Local<v8::Object> exports) {
exports->Set(Nan::New("hello").ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(Method)->GetFunction());
}
NODE_MODULE(hello, Init)
var addon = require('./build/Release/hello.node');
console.log(addon.hello()); // 'hello world'
{
"targets": [
{
"target_name": "hello",
"sources": [ "hello.cpp" ],
"include_dirs": [
"<!(node -e \"require('nan')\")"
]
}
]
}
- 准备编译环境( 在项目路径下)
- npm install -g node-gyp (全局安装)
- npm install nan
- node-gyp configure (会产生build文件夹)
# 方式1
cd build
make
# 方式2
node-gype rebuild
类的写法
#ifndef CLASS_H
#define CLASS_H
#include <nan.h>
class MyObject : public Nan::ObjectWrap {
public:
static void Init(v8::Local<v8::Object> exports);
private:
explicit MyObject(double value = 0);
~MyObject();
static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);
static void GetValue(const Nan::FunctionCallbackInfo<v8::Value>& info);
static void PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info);
static void Multiply(const Nan::FunctionCallbackInfo<v8::Value>& info);
static Nan::Persistent<v8::Function> constructor;
double value_;
};
#endif // CLASS_H
Nan::Persistent<v8::Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
MyObject::~MyObject() {
}
void MyObject::Init(v8::Local<v8::Object> exports) {
Nan::HandleScope scope;
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Nan::SetPrototypeMethod(tpl, "value", GetValue);
Nan::SetPrototypeMethod(tpl, "plusOne", PlusOne);
Nan::SetPrototypeMethod(tpl, "multiply", Multiply);
constructor.Reset(tpl->GetFunction());
exports->Set(Nan::New("MyObject").ToLocalChecked(), tpl->GetFunction());
}
void MyObject::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (info.IsConstructCall()) {
double value = info[0]->IsUndefined() ? 0 : info[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
} else {
const int argc = 1;
v8::Local<v8::Value> argv[argc] = { info[0] };
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
info.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
}
void MyObject::GetValue(const Nan::FunctionCallbackInfo<v8::Value>& info) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
info.GetReturnValue().Set(Nan::New(obj->value_));
}
void MyObject::PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
obj->value_ += 1;
info.GetReturnValue().Set(Nan::New(obj->value_));
}
void MyObject::Multiply(const Nan::FunctionCallbackInfo<v8::Value>& info) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
double multiple = info[0]->IsUndefined() ? 1 : info[0]->NumberValue();
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
const int argc = 1;
v8::Local<v8::Value> argv[argc] = { Nan::New(obj->value_ * multiple) };
info.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
#include <nan.h>
#include "myobject.h"
void InitAll(v8::Local<v8::Object> exports) {
MyObject::Init(exports);
}
NODE_MODULE(addon, InitAll)
var addon = require('./build/Release/addon.node');
var obj = new addon.MyObject(10);
console.log( obj.plusOne() );
console.log( obj.plusOne() );
console.log( obj.plusOne() );
console.log( obj.multiply().value() );
console.log( obj.multiply(10).value() );
var newobj = obj.multiply(-1);
console.log( newobj.value() );
console.log( obj === newobj );