作为桌面端,还是很注重与本机的交互操作的。这是桌面端的优势之一,至少目前web端是比较难实现的。虽然有了Node这种用js来写服务的方式,但有些功能实现起来还是不容易。如果能调用c++类库,扬长避短、强强联合,可能会事半功倍。
最近刚好有这方面的需要,想通过桌面端调用现有的c++工具库,于是翻遍了网络上现有的各中资料,有过时的、有可以借鉴的、有可以参考思路的,整理一下,方便同道中人共同探讨。
一、搭建electron-vue框架
前面有详细的介绍,这里就不再赘述了。Electron+Vue开发轻量级应用
二、准备c++的dll
为了说明流程,我这里借鉴了网上讲的最多的一个例子,亲自写过测试过,是可用的。当然如果您有现成的,就可以跳过这一步了。c++类库过程如下:
- 使用vs创建
动态链接库
项目
image.png
2.修改配置类型为动态库.dll
image.png
三、安装加载C++类库需要的工具包
- ffi
Foreign Function Interface
调用动态链接库,俗称调DLL,实现调用C/C++代码,从而实现许多node不好实现的功能,或复用诸多已实现的函数功能。 - ref里面含有c++支持的所有基本数据类型,用于接口的参数映射
# yarn add ffi ref 或者
cnpm install ffi
cnpm install ref
- 函数声明,创建一个myAdd.h头文件
被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和链接的。
__declspec(dllexport)用于Windows中的动态库中,声明导出函数、类、对象等供外面调用,省略给出.def文件。即将函数、类等声明为导出函数,供其它程序调用,作为动态库的对外接口函数、类等。
extern "C"
{
__declspec(dllexport) int funAdd(int a, int b);
}
- 函数定义,创建一个myAdd.cpp文件
#include "myAdd.h"
// 定义一个简单的方法
int funAdd(int a, int b)
{
return (a + b);
}
- 生成dll,右键项目选择
生成
即可,然后将对应dll文件拷贝到项目的static文件夹下
四、在页面中声明dll中开放的方法
- 首先引入相关package
const ref = require('ref');
const refArray = require('ref-array')
const ffi=require("ffi");
- 声明想要调用的方法
# 定位dll的路径
var dllPath = path.join(__static, "myAddDll.dll")
const myAddDll = new ffi.Library(dllPath, {
'funAdd': // 声明这个dll中的一个函数
[
'int', [ref.types.int, ref.refType('int')], // 第一个int是返回类型,[]里面的是参数的数据类型
// 这三种写法的int都是可以的
],
});
- 调用c++方法
const result = myAddDll.funAdd(5,8)
console.log(result)// 13
- 当数据类型遇到Byte[]
var byteArray = refArray(ref.types.byte)
const myAddDll2 = new ffi.Library(dllPath, {
'funAdd2': [
'int',['ushort', byteArray]
]
})
var psdByte = new byteArray(100)
const psdBuffer = Buffer.from('Hello World') // Hello World转换Buffer
// 通过Buffer循环复制, 比较啰嗦
for (let i = 0, l = psdBuffer.length; i < l; i++) {
psdByte[i] = psdBuffer[i]
}
// 读写数据之前需要先登录
retcode = myAddDll2.funAdd2(1,psdByte)
五、可能遇到的问题
- ……binding.node' was compiled against a different Node.js version using这是最让我头疼的一个问题,也是大部分人常遇到的问题,尝试了很多方法,终于找到了行得通的方法:
npm install --save-dev electron-rebuild
./node_modules/.bin/electron-rebuild.cmd
- 报错Error: Dynamic Linking Error: Win32 error 126
原因:引入的dll路径错了,找不到dll文件 - 报错Error: Dynamic Symbol Retrieval Error: Win32 error 127
原因:dll有问题,没有找到对应的方法,请核对方法名称、参数和返回参数类型,确定调用的方法是声明导出了的 - 报错Error: Dynamic Linking Error: Win32 error 193
原因:dll的位数不对,请拷贝相同位数的dll文件x86还是x64要搞清楚。
参考文档
1. node-ffi使用指南
2.使用ffi-napi引入C++的dll
3.【electron-vue】在electron中调用C++的dll(ffi库)
4.如何在Electron中调用Dll
网友评论