当前位置: 首页 > article >正文

使用node-addon-api实现从c到nodejs模块全流程

目录

1 前言

2 安装nodejs

3 安装开发工具链

3.1 安装node-gyp

3.2 安装编译工具链(C/C++ 编译器)

4 初始化 Node.js 项目

4.1 创建项目目录

4.2 初始化 package.json

4.3 安装必要的库

5 编写代码

5.1 创建项目结构

5.2 编写动态库代码

5.3 编写 Node.js 原生模块代码

5.4 配置 binding.gyp

6 编译模块

7 测试模块


1 前言

我们的客户端是使用electron打包的前端程序,因为electron基于nodejs的,所以我们想实现先用c/c++实现拉流+内容解密+硬件解码+硬件格式转换的功能,然后让nodejs去调用c/c++的库,我们调研了下面3种方式:

  1. webassembly:因为webassembly是运行在沙箱环境,无法访问网络资源,所以这种方式不可用。
  2. node-ffi:这种方式不需要编写额外的c/c++代码,直接使用已经编译好的库就行,但我们验证发现使用node-ffi对node版本有要求,高于16的node版本无法使用,这违反了公司的安全规定。
  3. node-addon-api:这种方式需要对每一个暴露的接口重写一遍,这稍微麻烦,但好在性能比较好且对于node版本没有什么限制,我们最终使用这种方法。

作为一个前端小白,下面详细的记录下如何将一个c语言写的库使用node-addon-api封装为nodejs的模块,过程中遇到一些坑并最终解决,希望其他朋友可以参考下。感谢chatgpt给予的帮助,下面内容参考chatgpt的回答,且已经得到完全的验证。

安装nodejs

在我的debian环境下使用下面命令来安装nodejs

curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo
apt-get install -y nodejs

3 安装开发工具链

3.1 安装node-gyp

sudo npm install -g node-gyp

3.2 安装编译工具链(C/C++ 编译器)

sudo apt-get install -y build-essential

4 初始化 Node.js 项目

4.1 创建项目目录

mkdir c2node_example
cd c2node_example

4.2 初始化 package.json

npm init -y

4.3 安装必要的库

npm install node-addon-api

5 编写代码

5.1 创建项目结构

创建以下文件和目录:

c2node_example
├── binding.gyp
├── index.js
├── native
│   ├── addon.cc
│   ├── example.c
│   └── example.h
└── package.json

5.2 编写动态库代码

创建 native/example.c 和 native/example.h:

native/example.h:

#ifndef EXAMPLE_H
#define EXAMPLE_H

#ifdef __cplusplus
extern "C" {
#endif

int add(int num1, int num2);
void say_hello(const char* name);

#ifdef __cplusplus
}
#endif

#endif

native/example.c:

#include <stdio.h>
#include "example.h"

int add(int num1, int num2) {
        return num1 + num2;
}

void say_hello(const char* name) {
        printf("hello,%s!\n", name);
}

生成动态库:

cd native
gcc -shared -fPIC -o libexample.so example.c
cd ..

5.3 编写 Node.js 原生模块代码

创建 native/addon.cc,用于封装 C 动态库。

native/addon.cc:

#define NAPI_DISABLE_CPP_EXCEPTIONS
#include <napi.h>
#include "example.h"

Napi::Value Add(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();

    int a = info[0].As<Napi::Number>().Int32Value();
    int b = info[1].As<Napi::Number>().Int32Value();

    int result = add(a, b);
    return Napi::Number::New(env, result);
}

Napi::Value SayHello(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();

    std::string name = info[0].As<Napi::String>().Utf8Value();
    say_hello(name.c_str());
    return env.Null();
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
    exports.Set("add", Napi::Function::New(env, Add));
    exports.Set("sayHello", Napi::Function::New(env, SayHello));
    return exports;
}

NODE_API_MODULE(addon, Init)

5.4 配置 binding.gyp

binding.gyp

{
  "targets": [
    {
      "target_name": "addon",
      "sources": ["native/addon.cc"],
      "include_dirs": ["./node_modules/node-addon-api"],
      "libraries": ["-L../native", "-lexample"],
      "cflags": ["-fno-exceptions"],
      "xcode_settings": {
        "OTHER_CFLAGS": ["-fexceptions"]
      }
    }
  ]
}

这里遇到了一个坑,可就是libraries的配置,不能写成-L./native,因为会在build目录下执行相应的命令,这个花费了很长时间才解决。

6 编译模块

在项目根目录运行以下命令:

npx node-gyp configure
npx node-gyp build

生成的模块文件位于 build/Release/addon.node

7 测试模块

编写 index.js:

const addon = require('./build/Release/addon');

console.log("5 + 3 =", addon.add(5, 3)); // 输出: 5 + 3 = 8 
addon.sayHello("Node.js"); // 输出: Hello, Node.js!

运行测试:


http://www.kler.cn/a/403974.html

相关文章:

  • 探索Python编程:从入门到实践的高效指南
  • C指针之舞——指针探秘之旅(2)
  • (二)Ubuntu22.04+Stable-Diffusion-webui AI绘画 中英双语插件安装
  • IDEA2023设置控制台日志输出到本地文件
  • 永磁同步电机无速度算法--滑模观测器(PLL)
  • 前端研发高德地图,如何根据经纬度获取地点名称和两点之间的距离?
  • 26届JAVA 学习日记——Day14
  • 【学习笔记】AD智能PDF导出(装配文件)
  • React的API✅
  • reactflow 中 useReactFlow 模块作用
  • IDEA 2024安装指南(含安装包以及使用说明 cannot collect jvm options 问题 四)
  • Ubuntu 18.04 安装 Docker
  • ubuntu中使用ffmpeg和nginx推流rtmp视频
  • 大数据新视界 -- Hive 数据仓库:架构深度剖析与核心组件详解(上)(1 / 30)
  • 电源模块自动化测试系统的优势体现在哪些方面?-纳米软件
  • 科技赋能健康:多商户Java版商城系统引领亚健康服务数字化变革
  • uniapp奇怪bug汇总
  • Java项目实战II基于Spring Boot的工作流程管理系统设计与实现(开发文档+数据库+源码)
  • 图像处理 - 色彩空间转换
  • Dockerfile复制目录进入镜像里
  • 主机管理工具 WGCLOUD v3.5.6 更新了哪些特性
  • 注意原函数平行,取log后就不平行了
  • 晶圆测试中自动化上下料的重要性与应用
  • bpmn.js显示流程图
  • 重载函数的应用
  • MySQL数据库运维及集群搭建