JS集成C++参数传值技术选型

Electron集成C++技术选型

技术论证结果:

通过node-gyp实现js和c++相互调用传参,后期再与Electron集成,直接写JS即可。

选型论证需求

研究下c++如何与Electron集成(初步看有两种方案,nodejs集成c++,或者将c++编译wasm,了解两种方案的优劣)

  1. 实现js中调用c++函数
  2. 实现c++中调用js函数 需要探索参数传递问题,除了简单的类型,还得看一些复杂的参数如何传递,如对象、函数 写几个demo进行验证,出一篇c++与Electron集成的详细文档

选型方案一:nodejs集成c++(优选)

1. 技术方案特点

Node.js 集成 C++ 是通过 Node.js 的插件机制,将 C++ 模块导入到 Electron 应用中,并实现 JavaScript 与 C++ 的互操作。

2. 优缺点分析

优点:

  • 直接利用 Node.js 的插件机制,简化了与 Electron 的集成过程,方便直接调用。

缺点:

  • 需要熟悉 Node.js 的插件开发,可能涉及 V8 引擎的 API 调用和内存管理,常规开发基本不涉及。

3. 选择理由

对于 Electron 集成 C++ 的首选技术方案,我会倾向于选择 Node.js 集成 C++,理由:

Electron中可以直接使用通过使用JS调用 C++,利用了 Node.js 的插件(node-gyp)机制,与 Electron 的集成相对简单直接。相比之下,将 C++ 编译为 Wasm 需要额外的工作和配置,同时直接进行语法编译转换,不方便调试,而且可能存在一些限制和兼容性问题。

选型方案二:c++编译wasm

1. 技术方案特点

将 C++ 代码编译为 WebAssembly (Wasm) 格式,可以在浏览器中直接运行,并与 JavaScript 高度集成,大致执行顺序1. 加载框架的 js 文件;2. 框架 js 文件自动加载并编译 wasm 文件;3. 执行 demo 文件。

2. 优缺点分析

优点:

  • 跨平台、高性能,与 JavaScript 高度集成,适用于前端和后端代码共享。
  • 避免了 Node.js 插件开发的复杂性。

缺点:

  • 需要安装额外C++编译环境,如使用 Emscripten 进行编译,直接进行语法编译后还需要进行加载调用wasm,才能使用wasm文件,相当于是将c++语法转化成js语法,编译调试起来困难。
  • WebAssembly 目前仍在发展中,可能存在一些限制和兼容性问题。

选型方案一:具体实现

1. 开发环境

电脑环境

复制代码
window10

node环境

arduino 复制代码
node版本 17.0.1 
npm install -g node-gyp // node-gyp:Node.js 编写 C++ 扩展的构建工具

python环境

复制代码
python-3.12.0

开发工具vscode

2. 示例说明

本demo示例分为两部分分别为js-cpp-xx和cpp-js-xx。

js-cpp-integration-demo说明:js调用c++文件,进行传值

cpp-js-integration-demo说明:cpp调用js文件,进行传值测试

3. 原理说明

addon.cpp文件中编写c++代码,binding.gyp文件

lua 复制代码
 |-- js-cpp-integration-demo
    |-- addon
        |-- build  // 打包和编译后的文件
        |-- addon.cpp // C++代码
        |-- binding.gyp // 编译配置
    |-- index.js // node入口文件,加载c++打包后文件 require('./addon/build/Release/addon.node');

4. 代码说明

代码执行步骤,以js-cpp-integration-demo为例:

bash 复制代码
# 导航到你的模块目录
cd xxx/demo/js-cpp-integration-demo/addon
​
npm install -g node-gyp
​
# 读取项目根目录下的 binding.gyp 文件,生成编译配置文件
node-gyp configure
​
# 通过配置文件编译原生Node.js模块
node-gyp build // *** 每次更改C++代码,需要重新编译 ***
​
cd xxx/demo/js-cpp-integration-demo
​
node ./index.js

index.js文件执行结果示例:

css 复制代码
// index.js中打印结果示例:
1.Adding: 13
2.函数回调结果: 测试文字
3.Send(js)Array: [ [ 'aa', 'bb', 'cc', 'dd' ], [ 'aaa', 'bbb', 'ccc', 'ddd' ] ]
Received(cpp): [[aa,bb,cc,dd],[aaa,bbb,ccc,ddd]]
4.Send(js)Object: {
  amount: 99,
  letters: [ [ 'aa', 'bb', 'cc', 'dd' ], [ 'aaa', 'bbb', 'ccc', 'ddd' ] ]
}
Received(cpp): {
  amount: 99.000000,
  letters: [['aa', 'bb', 'cc', 'dd'], ['aaa', 'bbb', 'ccc', 'ddd']]
}

index.js中文件代码:

javascript 复制代码
const addon = require('./addon/build/Release/addon');
// const addon = require('./addon/build/Debug/addon.node'); debugger使用
​
// 1. 调用cpp函数示例
console.log('1.Adding:', addon.add(3, 10));
​
// 2. 向cpp传递函数示例
addon.about(function(msg){
    console.log('2.函数回调结果:', msg);
})
​
// 3. 传二维数组值示例
const data = [["aa","bb","cc","dd"],["aaa","bbb","ccc","ddd"]]
console.log('3.Send(js)Array:',  data);
addon.jsToCpp2DArray(data)
​
// 4. 传复杂对象数组值示例
const obj ={ "amount":99, "letters":[["aa","bb","cc","dd"],["aaa","bbb","ccc","ddd"]] }
console.log('4.Send(js)Object:',  obj);
addon.jsToCppObject(obj)

说明:示例1和示例2分别为JS调用C++函数和C++调用JS函数示例,并且通过函数进行互相传值。(cpp-js-integration-demo不再赘述,C++调用JS函数,参照示例2)

C++代码见demo中addon文件夹中,代码过长不在文档中展示。

相关文档

【1】记一次完整 C++ 项目编译成 WebAssembly 的实践

【2】node.js调用C++的一种方法

【3】使用node-addon-api编写c/c++扩展(传递复杂对象)

相关推荐
我不是懒洋洋1 分钟前
从零实现一个分布式限流器:令牌桶与漏桶
c++
不负岁月无痕1 小时前
STL --C++哈希表封装unordered_map/set
c++·visualstudio·哈希算法·散列表·unordered
闻道且行之10 小时前
TurboOCR:基于PP-OCRv6的极速Windows离线OCR工具,深度解析3.4GB依赖背后的技术架构
c++·人工智能·python·qt·机器学习·ocr
c2385612 小时前
Bug 猎手入门指南
c++·算法·bug
玖玥拾14 小时前
C++ 数据结构 八大基础排序算法专题
数据结构·c++·算法·排序算法
YYYing.14 小时前
【C++大型项目之高性能服务器框架 (七) 】Socket与ByteArray模块
服务器·c++·后端·框架·高性能·c/c++
从零开始的代码生活_15 小时前
C++ list 原理与实践:双向链表、迭代器与简化实现
开发语言·c++·后端·学习·算法·链表·list
charlie11451419115 小时前
现代C++工程实践——WeakPtr 第二关:核心骨架与控制块
开发语言·c++
2401_8697695916 小时前
内容9 string 1
c++
ComputerInBook17 小时前
C & C++ 中的关键字 volatile 之详解
c语言·c++·volatile·编译器优化