- Native Abstractions for Node.js (nan)
- nan方式的好处:使用nan方式,编写的c++插件接口,会自动兼容不同版本的nodejs
- 因此,你的代码只需要随着 nan版本升级出现的改变而改变,至于Nodejs,nan会帮你兼容(前提是nan支持该版本的nodejs)
1、先安装node.js和python
2、新建一个demo项目: 创建demo目录,并进入其中,然后运行下面命令。
mkdir demo
cd demo
npm init
运行npm init时,之后会生成一个package.json(具体内容与输入参数有关):
{
"name": "demo",
"version": "1.0.0",
"description": "a demo for node call native functions",
"main": "demo.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"node"
],
"author": "Li XianJing",
"license": "ISC"
}
3、在项目路径下
npm install -g node-gyp (全局安装)
npm install nan 这个也可以用 npm install nan bindings --save
解释
node-gyp是C++扩展的编译工具;
nan和bindings包含了C++扩展需要的头文件;
4、用C++编写原生代码( 为了让目录结构整洁一点,我们把代码放到native只目录下)。
下面的文件(native/demo.cc),添加一个Add方法,计算两个数之和:
#include <nan.h>
void Add(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (info.Length() < 2) {
Nan::ThrowTypeError("Wrong number of arguments");
return;
}
if (!info[0]->IsNumber() || !info[1]->IsNumber()) {
Nan::ThrowTypeError("Wrong arguments");
return;
}
double arg0 = info[0]->NumberValue();
double arg1 = info[1]->NumberValue();
v8::Local<v8::Number> num = Nan::New(arg0 + arg1);
info.GetReturnValue().Set(num);
}
void Init(v8::Local<v8::Object> exports) {
exports->Set(Nan::New("add").ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(Add)->GetFunction());
}
NODE_MODULE(demo, Init)
5、写一个node-gyp的配置文件(文件名固定为binding.gyp),用来编译C++代码。
{
"targets": [
{
"target_name": "demo",
"sources": [ "native/demo.cc" ],
"include_dirs": [
"<!(node -e \"require('nan')\")"
]
}
]
}
6、编写一个JS文件(demo.js)),让它调用原生代码。
var demo = require('bindings')('demo.node')
console.log('add(3, 5) => ', demo.add(3, 5))
7、运行配置脚本(如果没有增删文件,不需要每次运行)
node-gyp configure
8、编译C++程序。
node-gyp build
注意:有修改的时候最好用:node-gyp rebuild
9、运行JS代码,看看是否工作。
node demo.js
其他参考:
addon其实就是一个桥梁,利用V8提供的API,可以实现JavaScript和C++的互相调用,打通JavaScript和C++之间的接口。
我们先编写一个小例子,大概了解js层和addon之间数据交换的过程。需要三个文件:
binding.gyp:其实就是一个json文件,因为要使用node-gyp进行编译,该文件可以说是定义了一些编译规则。
addon.cc: 该文件就是我们需要编写的addon,node-gyp借助vs编译后最终会生成
addon.node二进制文件。
index.js: 该文件就是测试js,在js层可以加载addon,调用addon对外的函数。
void Foo(const v8::FunctionCallbackInfo<v8::Value> &args)
{
// from v8 to cpp
v8::Isolate* isolate = args.GetIsolate();
v8::String::Utf8Value str(isolate, args[0]);
std::string cppStr(*str);
// back to v8
v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, cppStr.c_str(), v8::String::kNormalString);
}
1. npm 安装windows-build-tools
cmd管理员模式打开,执行下面命令:
npm install --global --production windows-build-tools
等待执行完成,重启CMD
2. windows下安装node-gyp
node-gyp就是为node编译c++扩展的时候使用的编译工具。
安装方法:
npm install -g node-gyp
3. 配置依赖
npm config set python python2.7
npm config set msvs_version 2015
如果不出意外的话我们就可以用node-gyp进行构建了。
如果出现问题可以参考node-gyp的github主页。
#include <nan.h>
NAN_METHOD(multi)
{
int result = 1;
for (int i = 0; i < info.Length(); i++)
{
result *= info[i]->NumberValue();
}
info.GetReturnValue().Set(Nan::New(result));
}
NAN_METHOD(add)
{
int result = 0;
for (int i = 0; i < info.Length(); i++)
{
result += info[i]->NumberValue();
}
info.GetReturnValue().Set(Nan::New(result));
}
void init(v8::Local<v8::Object> exports)
{
Nan::SetMethod(exports, "multi", multi);
Nan::SetMethod(exports, "add", add);
}
NODE_MODULE(demo, init); // demo-导出模块的名称