Node-API 学习一

别担心!学习 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. 下一步学习​

  1. 异步操作 (napi_create_async_work)
  2. 线程安全 (napi_threadsafe_function)
  3. 高性能 Buffer 处理 (napi_create_arraybuffer)

如果你卡住了,可以随时问我!现在你可以先试试上面的例子,确保能跑通后再深入更复杂的功能。 😊

相关推荐
用户278860728567几秒前
别把 AI 查询结果只塞进聊天框:SessionView 与业务页面接线
前端
程序员鱼皮1 分钟前
Personal Agent 是什么?为什么大厂都抢着做?连 DeepSeek Bot 都来了。。
前端·后端·ai编程
m0_587383009 分钟前
碰碰好评卡功能落地全流程实战指南 附核心逻辑与常见问题解决方案
java·前端·数据库·后端·struts·需求分析
子轩学长说10 分钟前
Workbuddy独立文件浏览器新上线,彻底告别WPS和office全家桶~
前端
nyaomaru11 分钟前
如何用 Jev 从 PR 中提取 “Why” 并写入 CHANGELOG?🤔
前端·typescript
Shirley~~11 分钟前
从0搭建一个3D立体场景:光影与交互全解析
前端·3d
Dovis(誓平步青云)12 分钟前
一年1956亿行:智能电表场景下的时序数据存储实践
运维·前端·自动化·音视频·prometheus
兰亭妙微UI设计公司13 分钟前
兰亭妙微分享:高手设计登录页的12种切入点
开发语言·前端·javascript
前端Baymax16 分钟前
静默的 86 小时:全链 402 停摆与零告警的故障复盘
开发语言·前端·javascript
要开心吖ZSH18 分钟前
定时任务从外部调度搬回本地 @Scheduled:一次连接池被打满的复盘与选型思考
前端·firefox