一、N-API 开发方式介绍
在 NAN 的开发方式下,一次编写好的代码在不同版本的 Node.js 下也需要重新编译,否则版本不符的话 Node.js 无法正常载入一个 C++ 扩展。即一次编写,到处编译。
而 N-API 相较于 NAN 来说,它把 Node.js 的所有底层数据结构全部黑盒化,抽象成 N-API 当中的接口。
不同版本的 Node.js 使用同样的接口,这些接口是稳定地 ABI 化的,即应用二进制接口(Application Binary Interface)。这使得在不同 Node.js 下,只要 ABI 的版本号一致,编译好的 C++ 扩展就可以直接使用,而不需要重新编译。
N-API 以 C 的风格提供稳定 ABI 接口,消除了 Node.js 版本的差异;消除 JavaScript 引擎的差异(如 Google V8、Microsoft ChakraCore 等)。
而这些 API 主要就是用来创建和操作 JavaScript 的值了,我们就再也不用直接使用 Google V8 提供的数据类型了。毕竟在 NAN 中,就算我们有时候看不到 Google V8 的影子,实际上在宏展开后还是无数的 Google V8 数据结构。
为了达成上述隐藏的目标,N-API 的姿势就变成了这样:
提供头文件 node_api.h;
任何 N-API 调用都返回一个 napi_status 枚举,来表示这次调用成功与否;
N-API 的返回值由于被 napi_status 占坑了,所以真实返回值由传入的参数来继承,如传入一个指针让函数操作;
所有 JavaScript 数据类型都被黑盒类型 napi_value 封装,不再是类似于v8::Object、v8::Number 等类型;
如果函数调用不成功,可以通过 napi_get_last_error_info 函数来获取最后一次出错的信息。
二,编译工具 node-gyp
node-gyp 是基于 GYP的。它会识别包或者项目中的 binding.gyp 文件,然后根据该配置文件生成各系统下能进行编译的项目,如 Windows 下生成 Visual Studio 项目文件(*.sln 等),Unix 下生成 Makefile。在生成这些项目文件之后,node-gyp 还能调用各系统的编译工具(如 GCC)来将项目进行编译,得到最后的动态链接库 *.node 文件。
安装:
npm install -g node-gyp
创建编译描述文件binding.gyp:
{ "targets": [ { "target_name": "hello", "sources": [ "./src/hello.cc" ] } ] }
编译命令:
node-gyp rebuild
编译一下代码失败,原因是要求系统 python 版本大于 3.6,暂时搁置编译:
#include <node_api.h> // 实际暴露的方法,这里只是简单返回一个字符串 napi_value HelloMethod (napi_env env, napi_callback_info info) { napi_value world; napi_create_string_utf8(env, "world", 5, &world); return world; } // 扩展的初始化方法,其中 // env:环境变量 // exports、module:node模块中对外暴露的对象 void Init (napi_env env, napi_value exports, napi_value module, void* priv) { // napi_property_descriptor 为结构体,作用是描述扩展暴露的 属性/方法 的描述 napi_property_descriptor desc = { "hello", 0, HelloMethod, 0, 0, 0, napi_default, 0 }; napi_define_properties(env, exports, 1, &desc); // 定义暴露的方法 } NAPI_MODULE(hello, Init); // 注册扩展,扩展名叫做hello,Init为扩展的初始化方法
调用:
为方便调用扩展,先安装bindings。
npm install --save bindings
调用刚编译的扩展:
var addon = require('bindings')('hello'); console.log( addon.hello() );
参考:
https://xcoder.in/2017/07/01/nodejs-addon-history
https://www.cnblogs.com/chyingp/p/nodejs-learning-napi.html
用 Rust 和 N-API 开发高性能 Node.js 扩展
https://zhuanlan.zhihu.com/p/234914336
修改时间 2022-01-10