美文网首页
07、electron调用c++的dll库

07、electron调用c++的dll库

作者: 仙人掌开不了花 | 来源:发表于2021-05-31 16:59 被阅读0次
       作为桌面端,还是很注重与本机的交互操作的。这是桌面端的优势之一,至少目前web端是比较难实现的。虽然有了Node这种用js来写服务的方式,但有些功能实现起来还是不容易。如果能调用c++类库,扬长避短、强强联合,可能会事半功倍。
       最近刚好有这方面的需要,想通过桌面端调用现有的c++工具库,于是翻遍了网络上现有的各中资料,有过时的、有可以借鉴的、有可以参考思路的,整理一下,方便同道中人共同探讨。
    

    一、搭建electron-vue框架

    前面有详细的介绍,这里就不再赘述了。Electron+Vue开发轻量级应用

    二、准备c++的dll

    为了说明流程,我这里借鉴了网上讲的最多的一个例子,亲自写过测试过,是可用的。当然如果您有现成的,就可以跳过这一步了。c++类库过程如下:

    1. 使用vs创建动态链接库项目
      image.png
      2.修改配置类型为动态库.dll
      image.png

    三、安装加载C++类库需要的工具包

    1. ffiForeign Function Interface调用动态链接库,俗称调DLL,实现调用C/C++代码,从而实现许多node不好实现的功能,或复用诸多已实现的函数功能。
    2. ref里面含有c++支持的所有基本数据类型,用于接口的参数映射
    # yarn add ffi ref 或者
    cnpm install ffi
    cnpm install ref
    
    1. 函数声明,创建一个myAdd.h头文件

    被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和链接的。
    __declspec(dllexport)用于Windows中的动态库中,声明导出函数、类、对象等供外面调用,省略给出.def文件。即将函数、类等声明为导出函数,供其它程序调用,作为动态库的对外接口函数、类等。

    extern "C"
    {
        __declspec(dllexport) int funAdd(int a, int b);
    }
    
    1. 函数定义,创建一个myAdd.cpp文件
    #include "myAdd.h"
    // 定义一个简单的方法
    int funAdd(int a, int b)
    {
      return (a + b);
    }
    
    1. 生成dll,右键项目选择生成即可,然后将对应dll文件拷贝到项目的static文件夹下

    四、在页面中声明dll中开放的方法

    1. 首先引入相关package
    const ref = require('ref');
    const refArray = require('ref-array')
    const ffi=require("ffi");
    
    1. 声明想要调用的方法
    # 定位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都是可以的
        ],
    });
    
    1. 调用c++方法
    const result = myAddDll.funAdd(5,8)
    console.log(result)// 13
    
    1. 当数据类型遇到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)
    

    五、可能遇到的问题

    1. ……binding.node' was compiled against a different Node.js version using这是最让我头疼的一个问题,也是大部分人常遇到的问题,尝试了很多方法,终于找到了行得通的方法:
    npm install --save-dev electron-rebuild
    ./node_modules/.bin/electron-rebuild.cmd
    
    1. 报错Error: Dynamic Linking Error: Win32 error 126
      原因:引入的dll路径错了,找不到dll文件
    2. 报错Error: Dynamic Symbol Retrieval Error: Win32 error 127
      原因:dll有问题,没有找到对应的方法,请核对方法名称、参数和返回参数类型,确定调用的方法是声明导出了的
    3. 报错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

    相关文章

      网友评论

          本文标题:07、electron调用c++的dll库

          本文链接:https://www.haomeiwen.com/subject/fucbsltx.html