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
  • 使用 printfconsole.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

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

相关推荐
whysqwhw4 小时前
Node-API 学习二
前端
Jenna的海糖4 小时前
Vue 中 v-model 的 “双向绑定”:从原理到自定义组件适配
前端·javascript·vue.js
一碗清汤面4 小时前
打造AI代码审查员:使用 Gemini + Git Hooks 自动化 Code Review
前端·git·代码规范
Sagittarius_A*4 小时前
SpringBoot Web 入门指南:从零搭建第一个SpringBoot程序
java·前端·spring boot·后端
我是ed4 小时前
# Vue 前端封装组件基础知识点
前端
芦苇Z4 小时前
CSS :has() 父级选择器与关系查询
前端·css
前端康师傅4 小时前
Javascript 中循环的使用
前端·javascript
毕了业就退休4 小时前
从 WebSocket 转向 SSE:轻量实时推送的另一种选择
前端·javascript·https
子兮曰4 小时前
🚀 图片加载速度提升300%!Vue/React项目WebP兼容方案大揭秘
前端·vue.js·react.js