使用N-API 写 Node.js 的 C语言扩展

一、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

声明:本站所有文章和图片,如无特殊说明,均为原创发布。商业转载请联系作者获得授权,非商业转载请注明出处。
真诚赞赏,手留余香
赞赏
随机推荐
Debian11 安装笔记4:安装常用软件
Photoshop 使用插件支持 webp 格式的文件
MySQL 使用 DATE_FORMAT() 和 FROM_UNIXTIME() 格式化时间
Node.js 的 URL 的模块
WordPress关闭自动草稿
WP_REST_Response 返回结果类
JavaScript 和 CSS 检测横屏适配
WordPress 后台添加菜单