Nodejs学习笔记Nodejs

NodeJs C/C++ 扩展入门

2020-03-22  本文已影响0人  野鸡没名

1、注:此教程默认你具备一定的 C/C++ 基础语法知识
2、如:指针、结构体等
3、本教程以 windows 操作系统为例,假设你会简单的使用 Visual Studio

系列文章

  1. C/C++ Addons 入门 Hello world!
  2. C/C++ Addons 对象参数及回调函数
  3. C/C++ Addons 非阻塞多线程回调
  4. C/C++ Addons windows 下 .dll 动态链接库 实用篇

完整代码

前置准备

工具
姿势

目前一共有三种方式可以编写 node.js 扩展,本文以官方推荐的 N-API 为例

起步

  1. 安装依赖
$ yarn add -D node-gyp # 就这一个依赖就够了
{
  "scripts": {
    "configure": "node-gyp configure",
    "build": "node-gyp build",
    "clean": "node-gyp clean",
    "rebuild": "node-gyp rebuild"
  }
}

ps: 下面的命令干的活都交给 VS 咯,不要去折腾命令咯(除非你没有VS)

  1. 新建 binding.gyp
{
  "targets": [
    {
      "target_name": "hello",
      "sources": [ "src/hello.c" ],
    }
  ]
}
  1. 生成目标平台项目
$ yarn configure
  1. 启动 Visual Studio
    image
    image

编写扩展

  napi_status 枚举
    · 调用任意 N-API 后返回值类型
  napi_extended_error_info 结构体
    · 表示调用 N-API 后发生的错误对象
  napi_env 结构体
    · 告诉 N-API 当前执行上下文,在调用 Addons 时自动(Init)传入
    · 调用任意多个、或嵌套 N-API 时候需要一直传递下去,不允许重用
  napi_callback_info 
    · 用于 Addons 获取 js 调用时候传入的上下文信息,如参数
  napi_value 不透明指针
    · N-API 提供的在 C、js 中间的一种数据类型
    · 任意的 js 数据类型都可以赋值给 napi_value,然后通过 N-API 提供的方法再把 napi_value 转成 C 语言的类型,反之亦然
  napi_threadsafe_function 不透明指针
    · 代表一个 js 的 function,在多线程模式下通过 napi_call_threadsafe_function 调用实现异步 😁

  # 函数
  napi_create_string_utf8
    · 创建 napi 类型的 string
    · 相当于 const str = 'Hello world!'
  napi_get_property
    · 从 napi 类型的对象中取值
    · 相当于对 json = { name: 'anan', age: 29 } 取值: console.log(json.name, json.age)

  napi_get_cb_info
    · **** 这个可以说是最重要的 API 了,再怎么强调也不为过 ****
    · 用于获取 js 的入参;如原始值类型、对象类型,甚至拿到 function 类型的指针地址
    · 可以说是 js 和 N-NAP 之前的桥梁

  napi_call_function
    · Addons 调用 js 回调
  napi_create_function
    · 创建 js 函数
  napi_get_global
    · 在 Addons 中获取 js 的 global 对象

#include <stdio.h>
#include <node_api.h>
#include <string.h>

napi_value Hello(napi_env env, napi_callback_info info) {
    size_t argc = 1;         // 只接受一个参数
    napi_value argv;         // 接收到的参数
    char n[40];
    char hello[90] = "Hello ";
    napi_value result;
    napi_get_cb_info(env, info, &argc, &argv, NULL, NULL);                     // 获取接收参数
    napi_get_value_string_utf8(env, argv, n, sizeof(n), NULL);                 // 将接收到的参数转换为 C 语言类型
    napi_create_string_utf8(env, strcat(hello, n), NAPI_AUTO_LENGTH, &result); // 拼接字符串

    return result;
}

napi_value Init(napi_env env, napi_value exports) {
    // 描述 hello 属性
    napi_property_descriptor desc = {
        "hello",
        NULL,
        Hello,
        NULL,
        NULL,
        NULL,
        napi_default,
        NULL };
    // 将 hello 挂载到 exports 上面 === require('hello.node').hello;
    napi_define_properties(env, exports, 1, &desc);

    return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

ps: 编写好C代码后,Ctrl+Shift+b (VS编译快捷键)

// const addon = require('./build/Debug/hello.node'); // 如果 VS 编译模式是 Debug
const addon = require('./build/Release/hello.node'); // 如果 VS 编译模式是 Release

console.log(addon.hello('world!'));
$ node test/hello.js
Hello world!

Boom Shakalaka

上一篇下一篇

猜你喜欢

热点阅读