藉由v8的强力支持,我们可以在node.js中可以很方便的使用一些c++库,或者自己编写一个动态链接库,并借v8库的连接,使之成为一个和其他node module一样可以直接通过require调用的方法.编写原生c++模块,可以地处理CPU密集型的操作,我们在日常使用中,也可以看到很多c++编写的npm包,如进行串口通讯用的包serialport、进行蓝牙通讯的包noble等等。
addons使用基本流程
- 编写c++源文件
- 创建binding.gyp文件
- 开始构建编译
- node-gyp configure(执行后目录下会多处build文件夹)
- node-gyp build (执行后build目录下回产生Release文件夹)
- require编译后的原声模块,在js中调用原生方法
1.1 基本用法
hello.cc源代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using namespace v8;
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
}
// 模块初始化函数,这里模块中创建一个名叫的hello的方法
void init(Local<Object> exports) {
/*
// 这样hello将成为导出模块的一个属性
//如果想设置Method作为到处模块本身,可以这样写:
void Init(Local<Object> exports, Local<Object> module) {
NODE_SET_METHOD(module, "exports", CreateObject);
}
*/
NODE_SET_METHOD(exports, "hello", Method);
}
//NODE_MODULE 是一个宏,export一个名叫addon的模块,init为初始化函数名
NODE_MODULE(addon, init)
binding.gyp:1
2
3
4
5
6
7
8{
"targets": [
{
"target_name": "addon",
"sources": [ "hello.cc" ]
}
]
}
调用测试脚本,test.js1
2
3
4
5// hello.js
const addon = require('./build/Release/addon');
console.log(addon.hello());
// Prints: 'world'
addons同步方法用法
js是一种弱类型语言,对数组/对象的使用都十分灵活,但是c++在这方面的灵活性就弱很多,变量的类型和
复合类型的使用都必须严格规定。同时,根据我们使用的场景,这里我列出了如下几种常见的调用方法类型。
- 单个简单类型如参,根据参数类型返回对应类型的返回值。
- 传入js函数,并同步执行
- 传入js对象,处理后返回新对象
简单类型参数处理和返回
1 | // 单个入参,根据不同入参类型,返回不同类型值 |
处理函数类型入参
1 | //创建用户返回的原生函数 |
处理对象类型入参
1 | //传入对象类型,并返回一个js对象 |
addons异步模块创建
之前的原生模块都是同步模块,调用后立即执行,调用者会一直等待被调用函数执行完成。如果我们想实现异步回调,就要借助libuv的强大魔力了。
libuv强制使用异步、事件驱动的编程风格。它的核心工作是提供一个event-loop,还有基于I/O和其它事件通知的回调函数。libuv还提供了一些核心工具,例如定时器,非阻塞的网络支持,异步文件系统访问,子进程等。
这里我们使用libuv的uv_default_loop来创建一个默认的事件循环.uv_queue_work()是一个便利的函数,它使得一个应用程序能够在不同的线程运行任务,当任务完成后,回调函数将会被触发.
后续会补上详细的libuv库和异步模块的使用笔记。
— 未完待续😢
这里,参考一下google到的资料,记录了一下c++addons的常规用法,便于后面自己使用的时候来查看。
参考1(英文)
参考2(英文)
参考3(中文)
参考4(中文)
libuv官方文档