别担心!学习 Node-API 确实需要一些实践和适应过程。让我们从最基础的实战开始,我会用最简单的方式带你入门,然后再逐步深入复杂功能。
1. 最简单的 Node-API 示例
目标 :写一个 C++ 函数,让 JS 调用并返回 "Hello from C++!"
。
步骤 1:创建项目
bash
mkdir hello_napi
cd hello_napi
npm init -y
步骤 2:安装必要工具
bash
npm install node-gyp -g # 构建工具
npm install bindings # 方便 JS 加载 C++ 模块
步骤 3:编写 C++ 代码
创建 hello.cc
:
arduino
#include <node_api.h>
// 1. 定义 C++ 函数,JS 可以调用
napi_value SayHello(napi_env env, napi_callback_info info) {
napi_value greeting;
napi_status status = napi_create_string_utf8(
env, "Hello from C++!", NAPI_AUTO_LENGTH, &greeting);
if (status != napi_ok) return nullptr; // 错误检查
return greeting;
}
// 2. 模块初始化(注册函数)
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_value fn;
// 把 C++ 函数 `SayHello` 注册为 JS 的 `sayHello`
status = napi_create_function(env, nullptr, 0, SayHello, nullptr, &fn);
if (status != napi_ok) return nullptr;
// 导出到 JS
status = napi_set_named_property(env, exports, "sayHello", fn);
if (status != napi_ok) return nullptr;
return exports;
}
// 3. 声明模块
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
**步骤 4:配置 binding.gyp
**
创建 binding.gyp
:
php
{
"targets": [
{
"target_name": "hello_napi",
"sources": ["hello.cc"],
"include_dirs": ["<!@(node -p "require('node-addon-api').include")"],
"dependencies": ["<!(node -p "require('node-addon-api').gyp")"]
}
]
}
步骤 5:编译 C++ 代码
node-gyp configure
node-gyp build
编译完成后,会在 ./build/Release/
下生成 .node
文件。
步骤 6:JS 调用 C++ 函数
创建 index.js
:
ini
const addon = require('./build/Release/hello_napi.node');
console.log(addon.sayHello()); // 输出: "Hello from C++!"
运行
node index.js
如果看到 Hello from C++!
,恭喜!你成功调用了 C++ 代码 🎉
2. 进阶:传递参数 & 返回计算值
目标:JS 传两个数字给 C++,计算它们的和并返回。
**修改 hello.cc
**
scss
napi_value Add(napi_env env, napi_callback_info info) {
// 1. 获取 JS 传入的参数
size_t argc = 2;
napi_value argv[2];
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
// 2. 检查参数数量
if (argc < 2) {
napi_throw_error(env, nullptr, "需要 2 个参数");
return nullptr;
}
// 3. 转换 JS 参数为 C++ 的 double
double a, b;
napi_get_value_double(env, argv[0], &a);
napi_get_value_double(env, argv[1], &b);
// 4. 计算并返回结果
napi_value result;
napi_create_double(env, a + b, &result);
return result;
}
// 在 Init 里注册 Add 函数
napi_value Init(napi_env env, napi_value exports) {
// ...(之前的代码)
napi_create_function(env, nullptr, 0, Add, nullptr, &fn);
napi_set_named_property(env, exports, "add", fn);
return exports;
}
**修改 index.js
**
arduino
console.log(addon.add(3, 5)); // 输出: 8
重新编译 & 运行
node-gyp rebuild
node index.js
现在你可以调用 addon.add(a, b)
计算两数之和了!
3. 常见问题 & 调试技巧
Q1:编译报错怎么办?
- 确保安装了
node-gyp
和 Python(python --version
应为 3.x) - 检查
binding.gyp
是否写对 - 查看
./build/Release/
是否生成了.node
文件
Q2:JS 调用时崩溃?
- 检查
napi_get_cb_info
是否正确获取参数 - 确保
napi_create_*
返回值是napi_ok
- 使用
printf
或console.log
调试 C++ 代码
Q3:如何传递对象?
scss
napi_value CreatePerson(napi_env env, napi_callback_info info) {
napi_value person;
napi_create_object(env, &person);
napi_value name;
napi_create_string_utf8(env, "Alice", NAPI_AUTO_LENGTH, &name);
napi_set_named_property(env, person, "name", name);
napi_value age;
napi_create_int32(env, 25, &age);
napi_set_named_property(env, person, "age", age);
return person;
}
JS 调用:
arduino
console.log(addon.createPerson()); // { name: "Alice", age: 25 }
4. 下一步学习
- 异步操作 (
napi_create_async_work
) - 线程安全 (
napi_threadsafe_function
) - 高性能 Buffer 处理 (
napi_create_arraybuffer
)
如果你卡住了,可以随时问我!现在你可以先试试上面的例子,确保能跑通后再深入更复杂的功能。 😊