使用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" {
#endifint 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.rhkb.cn/news/476189.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python3.11.9+selenium,获取图片验证码以及输入验证码数字

Python3.11.9+selenium,获取图片验证码以及输入验证码数字 1、遇到问题:登录或修改密码需要验证码 2、解决办法: 2.1、安装ddddocr pip install ddddocr 2.2、解析验证码函数 import ddddocr def get_capcha_text():#获取验证码图片ele_pic = driver.find_element(By.XPAT…

测试工程师如何在面试中脱颖而出

目录 1.平时工作中是怎么去测的&#xff1f; 2.B/S架构和C/S架构区别 3.B/S架构的系统从哪些点去测&#xff1f; 4.你为什么能够做测试这一行&#xff1f;&#xff08;根据个人情况分析理解&#xff09; 5.你认为测试的目的是什么&#xff1f; 6.软件测试的流程&#xff…

css水平居中+垂直居中

display:“flex”,position: “absolute”,top:“50%”,left:“50%”,transform: ‘translate(-50%, -50%)’

Linux 服务器使用指南:从入门到登录

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; &#x1f6a9;博主致力于用通俗易懂且不失专业性的文字&#xff0c;讲解计算机领域那些看似枯燥的知识点&#x1f6a9; 目录 一…

99.【C语言】数据结构之二叉树的基本知识

目录 1.树的定义 树是递归定义的 一些细碎的概念 2.树的判断法则 树结点结构的定义 自然想到的定义方法 左孩子右兄弟定义 3.树的应用:文件系统 4.树的特殊形式:二叉树 5.特殊的两类二叉树 满二叉树 完全二叉树 完全二叉树和满二叉树之间的关系 高度为h的完全二叉…

Bug:引入Feign后触发了2次、4次ContextRefreshedEvent

Bug&#xff1a;引入Feign后发现监控onApplication中ContextRefreshedEvent事件触发了2次或者4次。 【原理】在Spring的文档注释中提示到&#xff1a; Event raised when an {code ApplicationContext} gets initialized or refreshed.即当 ApplicationContext 进行初始化或者刷…

Ubuntu20.04从零安装IsaacSim/IsaacLab

Ubuntu20.04从零安装IsaacSim/IsaacLab 电脑硬件配置&#xff1a;安装Isaac sim方案一&#xff1a;pip安装方案二&#xff1a;预构建二进制文件安装1、安装ominiverse2、在ominiverse中安装isaac sim&#xff0c;下载最新的4.2版本 安装Isaac Lab1、IsaacLab环境克隆2、创建con…

低速接口项目之串口Uart开发(二)——FIFO实现串口数据的收发回环测试

本节目录 一、设计思路 二、loop环回模块 三、仿真模块 四、仿真验证 五、上板验证 六、往期文章链接本节内容 一、设计思路 串口数据的收发回环测试&#xff0c;最简单的硬件测试是把Tx和Rx连接在一起&#xff0c;然后上位机进行发送和接收测试&#xff0c;但是需要考虑到串…

算法编程题-排序

算法编程题-排序 比较型排序算法冒泡排序选择排序插入排序希尔排序堆排序快速排序归并排序 非比较型排序算法计数排序基数排序 本文将对七中经典比较型排序算法进行介绍&#xff0c;并且给出golang语言的实现&#xff0c;还包括基数排序、计数排序等非比较型的算法的介绍和实现…

【软考】系统架构设计师-信息系统基础

#信息系统基础核心知识点 信息系统5个基本功能&#xff1a;输入、存储、处理、输出和控制 诺兰模型&#xff1a;信息系统计划的阶段模型&#xff0c;6阶段 初始阶段&#xff0c;传播阶段&#xff0c;控制阶段&#xff0c;集成阶段&#xff0c;数据管理阶段&#xff0c;成熟阶…

【架构】主流企业架构Zachman、ToGAF、FEA、DoDAF介绍

文章目录 前言一、Zachman架构二、ToGAF架构三、FEA架构四、DoDAF 前言 企业架构&#xff08;Enterprise Architecture&#xff0c;EA&#xff09;是指企业在信息技术和业务流程方面的整体设计和规划。 最近接触到“企业架构”这个概念&#xff0c;转念一想必定和我们软件架构…

使用低成本的蓝牙HID硬件模拟鼠标和键盘来实现自动化脚本

做过自动化脚本的都知道&#xff0c;现在很多传统的自动化脚本方案几乎都可以被检测&#xff0c;比如基于root&#xff0c;adb等方案。用外置的带有鼠标和键盘功能集的蓝牙HID硬件来直接点击和滑动是非常靠谱的方案&#xff0c;也是未来的趋势所在。 一、使用蓝牙HID硬件的优势…

数据结构-二叉树_堆

目录 1.二叉树的概念 ​编辑1.1树的概念与结构 1.2树的相关语 1.3 树的表示 2. ⼆叉树 2.1 概念与结构 2.2 特殊的⼆叉树 2.2.2 完全⼆叉树 2.3 ⼆叉树存储结构 2.3.1 顺序结构 2.3.2 链式结构 3. 实现顺序结构⼆叉树 3.2 堆的实现 3.2.2 向下调整算法 1.二叉树的概…

【FPGA开发】AXI-Full总线接口介绍、FPGA搭建仿真平台

文章目录 协议解读接口介绍AW—写地址通道W—写数据通道B—写响应通道AR—读地址通道R—读数据通道 FPGA搭建仿真平台 本文主要介绍AXI-FULL的相关基础内容&#xff0c;AXI-Lite请移步&#xff1a; 【FPGA开发】AXI-Lite总线协议解读、Verilog逻辑开发与仿真、Alex Forencich代…

【已解决】“EndNote could not connect to the online sync service”问题的解决

本人不止一次在使用EndNote软件时遇到过“EndNote could not connect to the online sync service”这个问题。 过去遇到这个问题都是用这个方法来解决&#xff1a; 这个方法虽然能解决&#xff0c;但工程量太大&#xff0c;每次做完得歇半天身体才能缓过来。 后来再遇到该问…

Python深度学习环境配置(Pytorch、CUDA、cuDNN),包括Anaconda搭配Pycharm的环境搭建以及基础使用教程(保姆级教程,适合小白、深度学习零基础入门)

全流程导览 一、前言二、基本介绍2.1全过程软件基本介绍2.1.1 Pytorch2.1.2 Anaconda2.1.3 Pycharm2.1.4 显卡GPU及其相关概念2.1.5 CUDA和cuDNN 2.2 各部分相互间的联系和安装逻辑关系 三、Anaconda安装3.1安装Anaconda3.2配置环境变量3.3检验是否安装成功 四、Pycharm安装五、…

Java-05 深入浅出 MyBatis - 配置深入 动态 SQL 参数、循环、片段

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…

python成长技能之正则表达式

文章目录 一、认识正则表达式二、使用正则表达式匹配单一字符三、正则表达式之重复出现数量匹配四、使用正则表达式匹配字符集五、正则表达式之边界匹配六、正则表达式之组七、正则表达式之贪婪与非贪婪 一、认识正则表达式 什么是正则表达式 正则表达式&#xff08;英语&…

OpenCV与AI深度学习|16个含源码和数据集的计算机视觉实战项目(建议收藏!)

本文来源公众号“OpenCV与AI深度学习”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;分享&#xff5c;16个含源码和数据集的计算机视觉实战项目 本文将分享16个含源码和数据集的计算机视觉实战项目。具体包括&#xff1a; 1. 人…

Kafka 工作流程解析:从 Broker 工作原理、节点的服役、退役、副本的生成到数据存储与读写优化

Kafka&#xff1a;分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析&#xff1a;从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析&#xff1a…