electron 集成 调用 C++ dll 实践

#1 背景

最近需要做桌面端项目,打算尝试使用 electron 来开发,开发之前需要调研一些可行性,最关键的一点是:集成公司的统一登录 sdk,登录的 sdk 只有 C++ sdk 才能实现单点登录,所以这里就放弃去集成 js 的 sdk。

#2 怎么集成C++ dll

Google全网,最终放弃addons编译那种,太过于复杂,剩下两种方式:
第一种:node-ffi
第二种:node-ffi-napi

#3 为啥放弃node-ffi-napi这种方式

坦白说,napi 这种方式安装啥的都很方便,调试登录的过程中,出现的一个问题让我放弃了这种,登录接口需要传入回调函数,napi 的callback有点鸡肋(也可能是我没有用好吧,从网上查阅了很多资料最终放弃了),登录成功回调会让 electron crash

#4 准备环境

明确一点,我们开发的是一个win32程序,x86的(32位)
所以各个版本需要对齐(electron的
安装 Python 设置环境变量(后面遇到问题也会触发去设置)
npm install -g node-gyp
npm install -g windows-build-tools
继续安装(#node-12 为了让ffi支持node 12):
"dependencies": {
    "ffi": "github:lxe/node-ffi#node-12",
    "ref": "github:lxe/ref#node-12",
    "ref-struct": "github:lxe/ref-struct#node-12",
    "iconv-lite": "^0.5.0"
  }

#5 版本对齐很重要

我集成的 dll 是32位的,那么我选择 安装的 electron 也是 32位 win32 平台,参考 这里

npm install --arch=ia32 --platform=win32 --save-dev electron@5.0.13

#6 为什么选择 electron@5.0.13

我使用 node-ffi 集成 C++ dll,这个库目前支持到的 electron 就是 5.0 的版本,我是从最新的 7.x 退到 5.0 的版本才成功集成的。这期间琢磨了 1 天。安装完成执行

./node_modules/.bin/electron_rebuild

#7 打包工具

这个没啥可说的,考虑到 更新 ,选择 electron-build 比较靠谱

npm install electron-builder --save-dev

#8 nodejs <==> C++ 参数如何传递

调用 C++ 的方法都会涉及到一些参数和回调函数的传递,nodejs 和 C++ 的通讯的消息格式显然需要一个桥梁来转换,这个桥梁就是 Buffer

#9 调用demo

const LID = ffi.Library("./LsfSdk.dll", {
        Init: ["int", ["string", "pointer", "pointer", "pointer"]],
        LoginByGroup: ["int", ["string", "pointer", "pointer", LoginOptionsPtr]]
      });

#10 demo 说明

1 LsfSdk.dll 就是我需要集成的 C++ 提供的登录 SDK
2 Init,LoginByGroup 是里面的方法

#11 类型 ref ref-struct ref-array 等

nodejs 和 C 的类型需要一个转换 ref 已经包含了大部分了,如果有结构体 需要 安装 ref-struct,如果还有 ref 不包括的,可以继续搜索 ref-其它的类型
可以参考 这里

#12 char* pointer 和 struct *

char* 对应 string
windows 句柄等 对应 pointer
结构体指针 需要 使用 ref-struct 在 js 里面创建 一个 struct,然后使用const LoginOptionsPtr = ref.refType(LoginOptions)  // LoginOptions 是一个struct

#13 可能出现 wchar* 或 tchar* 的乱码问题

坦白说,这个问题困扰我很久,因为 nodejs 默认的字符串编码就是 utf8 ,当我直接传字符串的时候(我们的登录 sdk 是可以定制一些参数,比如文本 按钮颜色等),参数类型是 wchar* 或 tchar*(这个是C++里面的一个定义),类型就是 wchar* . 可以使用 iconv-lite 转码

iconv.encode(str, "ucs2");

#14 遇到问题先这样

rm -rf node_modules

#15 结语

electron 的版本升级都伴随一些 break changes 所以一开始选择好版本,做好可行性的验证很重要
如果需要集成 dll ,那么现阶段 electron 选择 5.0.13 比较合适,高版本会有很多问题无法解决。也许 node-ffi 后面会升级,能使用更新版本的 electron。
总的来说:electron 值得一试~,希望我的文章对你有帮助

#16 demo 主要代码

作者:张雪飞
出处:https://zhangxuefei.site/p/2653
版权说明:欢迎转载,但必须注明出处,并在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

2comments

  1. 项目最近也打算引入ffi进行dll集成
    用的是比较新的:vue-cli-plugin-electron-builder
    electron用的是:7.1.9

    看了您的文章感觉项目的版本也许要降低了

发表评论

电子邮件地址不会被公开。 必填项已用*标注