前言
基于Node-API构建C++插件目前主要两种构建方式,一种基于node-gyp,一种基于CMake。本文以Node-gyp为示例。
此外,开发Node插件,也有三种方式:
1、基于Nan
适用于Node.js v0.8~v14,不建议使用
2、直接使用内部 V8、libuv 和 Node.js 库
除非需要直接访问 Node-API 未暴露的功能,否则请使用 Node-API
3、Node-API(原N-API)
Node-API 是一种 C API,可确保跨 Node.js 版本和不同编译器级别的 ABI 稳定性。C++ API 可以更容易使用。为了支持使用 C++,该项目维护了一个名为 node-addon-api 的 C++ 封装器模块。此封装器提供可内联的 C++ API。
本文以Node-API为示例。
1、安装 Node.js
如果没有安装 Node.js,请去 Node.js 官网 下载合适版本的 Node.js 并安装。
如果未来不需要多个node版本,可以不使用例如nvm、fnm等包管理器软件
2、配置NPM源(可选项)
本文不再赘述
3、安装Python
本文不再赘述,注意配置Python的环境变量,供node-gyp使用
4、安装 node-gyp
node-gyp 是一个用于编译 Node.js 原生模块的命令行工具,你可以使用 npm 来安装它:
//安装node-gyp包
npm install -g node-gyp
注:在某些系统上可能需要管理员权限(如 Windows 上的管理员提示符或在 Linux/Mac 上使用 sudo)
//默认情况下,Windows 的执行策略可能禁止运行脚本,windows下PowerShell使用管理员权限
//1.使用管理员权限打开 PowerShell
// (Windows下可以同时按住Ctrl+Shift,然后点击Windows PowerShell打开软件,临时使用管理员权限)
//2.执行以下命令来更改执行策略:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
//这个命令将允许运行本地作者的脚本以及从 Internet 下载的经过签名的脚本
//它会询问你确认更改执行策略,输入 Y 然后回车
//请记住,改变执行策略可能会影响到系统的安全性
//如果你不想全局更改执行策略,可以尝试以更受限制的方式运行 node-gyp 命令
//将只为单次命令的执行临时绕过执行策略,而不影响全局设置
//windows下PowerShell内执行单次命令提权参考示例:
PowerShell -ExecutionPolicy ByPass -Command "node-gyp install 16.20.2"
如果系统内有具有多个Python版本,需要使用node-gyp的相关命令指明其使用的Python路径
5、安装Visual Studio的C++开发套件
多种方式(5.1、5.2选其一)下载相关套件,注意配置相关环境变量
5.1 按照node-nyp文档的指导
5.2 微软的node环境指导
nodejs-guidelines/windows-environment.md
文档内说明需要安装 Python2.7.10(不支持 v3.x.x)
笔者测试Python3.8.6可以,供参考
5.3 配置Visual Studio环境变量
Windows11下配置Visual Studio2022 环境变量(Windows下配置Visual Studio 通用)_visual studio环境变量设置-CSDN博客
笔者用户变量参考:
-
用户变量:
- PATH:
-
系统变量:
-
- INCLUED:
-
- LIB:
-
- PATH:
6、安装node-addon-api头文件
项目目录下运行如下代码,下载头文件库node-addon-api 使用C++版的头文件napi.h
//下载node插件头文件库
npm install node-addon-api
7、创建原生模块项目
在你的项目目录中,创建一个 binding.gyp 文件来描述你的编译配置,如:
{
"targets": [
{
"target_name": "your_module", #扩展的名称
"sources": [ "your_module.cc" ], #扩展的源文件
"include_dirs": [ #头文件的路径
"<!@(node -p "require('node-addon-api').include")"
],
"dependencies": [ #需要链接的库
"<!(node -p "require('node-addon-api').gyp")"
],
'defines': [ "NAPI_DISABLE_CPP_EXCEPTIONS" ],
"libraries": [
# 这里列出需要链接的第三方 DLL 文件。
# 如: "<(module_root_dir)/path/to/your/libfile.lib"
# 如: "WS2_32.lib"
],
# 条件编译
}
]
}
- 其中
"sources"需要列出所有的源代码文件。
8、编写 C++ 代码
在项目的源代码文件中(如 your_module.cc),你可以包含 napi.h 头文件进行开发:
#include <napi.h>
// ... 这里是你的 N-API 使用代码 ...
开发Node的插件,需要参考本文档:Node-API | Node.js v16 文档 (nodejs.cn)
提供一份add方法的插件参考代码:
// add.cc
#include <napi.h>
Napi::Value Add(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// 检查输入参数个数
if (info.Length() < 2) {
Napi::TypeError::New(env, "need two params").ThrowAsJavaScriptException();
return env.Undefined();
}
// 检查参数类型
if (!info[0].IsNumber() || !info[1].IsNumber()) {
Napi::TypeError::New(env, "param must be number type").ThrowAsJavaScriptException();
return env.Undefined();
}
// 执行加法
double value1 = info[0].As<Napi::Number>().DoubleValue();
double value2 = info[1].As<Napi::Number>().DoubleValue();
Napi::Number sum = Napi::Number::New(env, value1 + value2);
return sum;
}
// 初始化 addon
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "add"),
Napi::Function::New(env, Add));
return exports;
}
NODE_API_MODULE(addon, Init)
9、编译模块
接下来,在项目目录下使用以下命令来配置和编译你的原生模块:
node-gyp configure
node-gyp build
这些命令会使 node-gyp 下载对应的 Node.js 头文件,并编译你的模块。
可以使用
node-gyp help查看命令,参考:如何使用node-gyp
10、测试模块
写一份JS代码调用插件测试,如下:
// testAdd.js
const addon = require('./build/Release/addonAdd'); //addonAdd为binding.gyp内的target_name
console.log('This should be 8:', addon.add(3, 5));
调用命令:
//执行testAdd.js文件
node testAdd.js
11、参考文档
零基础开发 Node.js Addons 插件:Hello Node-API-腾讯云开发者社区-腾讯云 (tencent.com)