如何在Electron中调用Dll

客户端有些硬件的接口需要调试,是在电脑上连了一些硬件的设备,比如打印机、扫描仪或者进行串口通信等等。单靠JS是完成不了了,我们决定通过把C++或者C#把这些功能打包成Dll,然后在Electron客户端中通过Node调用Dll来实现所需要的功能。

Dll类型

先简单说一下什么是Dll,Dll是动态链接库文件,也是一种代码库的形式,与静态链接库相比,它是在每次程序运行的时候去调用,而静态链接库指令都会被打包到最后的exe文件里,所以如果函数有什么变化那就需要重新生成exe,那动态链接库就不需要这么做了。生成Dll可以通过VS来完成,可以选择使用C#或者C++开发,C#开发界面的比较方便,如果你的功能需要弹出一些界面,那就要用C#编写相应的Dll。不过这里要注意了,用C#语言编写生成的Dll和用C++语言编写生成的Dll是不一样的,通过C#生成的Dll需要.net的开发环境,而C++生成的Dll就没有限制。

Node如何调用Dll

Electron里调用Dll其实就是node调用Dll,刚才说了,生成的Dll不一样,那么调用方式也不一样。我是用到了这两个模块,ffi和edge,使用ffi调用C++生成的Dll,使用edge调用C#生成的Dll。ffi调用Dll

比如我这里有个ffiTest.dll的文件,里面有个导出的函数叫做joinStr,就是暴露的方法,给定两个字符串,然后会返回这两个参数的拼接结果。注意C++生成的Dll要使用C风格extern “C”否则可能找不到对应的方法名。var ffi = require('ffi');

var path = require('path');

var dllPath = path.resolve('ffiTest.dll');

var lib = ffi.Library(dllPath, {

'joinStr': ['string', ['string', 'string']],

})

var result = lib.joinStr('hello', 'world');

console.log(result); //打印 helloworld

更详细的示例可以参考它的教程。ffi.Library里第二个参数是一个Json结构,key表示是方法名,value示一个数组,数组的第一个参数是返回值类型,第二个参数是方法的列表,如果返回值是空的话,那数组第一个参数应该是void。如果返回值或者参数类型不知道是什么类型就写void*。要使用ffi中的类型表示C/C++语言中的类型,对照表如下基本类型

int8 Signed 8-bit Integer

uint8 Unsigned 8-bit Integer

int16 Signed 16-bit Integer

uint16 Unsigned 16-bit Integer

int32 Signed 32-bit Integer

uint32 Unsigned 32-bit Integer

int64 Signed 64-bit Integer

uint64 Unsigned 64-bit Integer

float Single Precision Floating Point Number (float)

double Double Precision Floating Point Number (double)

pointer Pointer Type

string Null-Terminated String (char *)

常见的C语言类型

byte unsigned char

char char

uchar unsigned char

short short

ushort unsigned short

int int

uint unsigned int

long long

ulong unsigned long

longlong long

ulonglong unsigned long long

size_t platform-dependent, usually pointer size

如果是指针类型,可以利用ref模块来表示var ref = require('ref');

var refArray = require('ref-array');

var intPtr = ref.refType('int'); //int*类型

var charPtr = 'hello'; //char*可以用string表示

//如果是个字符数组

var refArray = require('ref-array');

var charPtrPtr = refArray(ref.types.char, 50); //50个大小的数组

假如参数或者返回值是一个结构体,那就需要借助ref-struct模块来表示var ref = require('ref');

var FFI = require('ffi');

var Struct = require('ref-struct');

var TimeVal = Struct({

'tv_sec': 'long',

'tv_usec': 'long'

});

var TimeValPtr = ref.refType(TimeVal);

var lib = new FFI.Library(null, {

'gettimeofday': ['int', [TimeValPtr, 'pointer']]

});

var tv = new TimeVal();

lib.gettimeofday(tv.ref(), null);

console.log("Seconds since epoch: " + tv.tv_sec);edge调用Dll

edge这个模块非常强大,不仅可以在node中编写C#的代码也可以在C#中调用node的代码,它要求有一个.net4.5或者更高版本的环境。C#编写的Dll要通过async修饰后才能被node调用,大致像是这样using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace TestDll

{

public class StartUp

{

public async Task Invoke(object param)

{

return "Hello World!";

}

}

}

这样会生成一个TestDll.dll的文件,在node中var edge = require('edge');

var path = require('path');

var driver = edge.func({

assemblyFile: path.resolve('TestDll.dll'),

typeName: 'TestDll.StartUp',

methodName: 'Invoke'

})

//还可以这么写,var driver = edge.func(path.resolve('TestDll.dll'))

//这么写默认方法名就是Invoke,C#中class的名字就是StartUp。如果不一致的话调用就会报错

driver(null, function(err,result) {

if (err) {

throw err;

} else {

console.log(result);

}

});

利用edge其实可以在js直接编写C#的代码,那完全不用多个步骤还要去生成Dll了,但是这个项目里还依赖了别的Dll,这个语法还是有点懵,搞清楚后再试试直接写C#代码试试。

遇到的问题

过程总是那么地不顺利,即便知道了语法怎么写也会出现一些问题,总结了下大概是以下几种win32 error 126 Dll文件的路径写错了,或者Dll有相关的依赖,依赖没有放在与入口Dll在同一级目录下

win32 error 127 ffi定义的函数名、返回值类型或者参数类型与Dll定义的不一致

win32 error 193 Dll与当前的操作系统不匹配,当前系统是64位的Dll是32位的

在Electron的项目使用edge无法编译 edge是一个原生的模块需要用你当前安装node的版本重新编译,重新编译需要使用node-gyp,按下面几步执行即可npm install -g node-gyp

安装Python2.7和Visual Studio Build Tools或者VS2017。也可以从npm上下载npm install --global windows-build-tools

npm config set msvs_version 2017

node-gyp --python 你当前Python安装的路径

cd node_modules/edge

node-gyp configure

node-gyp build

如果觉得麻烦可以直接使用electron-edge-js就不用自己重新编译了,如果还是不行,就再装一下electron-rebuild然后执行.\node_modules\.bin\electron-rebuild.cmd

找不到windows对应的编译工具 这时候多半是下载的vs安装包没有安装Visual C++生成工具导致的。否则就可能是以下的几种情况:当前系统可能是安装了更高版本的vs,比如vs 2019,与你其他的模块版本不匹配,这时需要修改node-gyp msvs版本

vs安装在了自定义目录,检查是否包含中文,或直接选择C盘默认目录安装。最简单的通过执行npm install --msvs_version=2013覆盖安装即可

如果是在power shell中执行的命令需要设置node-gyp的目录,npm config set node-gyp="\node_modules\node-gyp\bin\node-gyp.js

dll找不到dll electron_如何在Electron中调用Dll相关推荐

  1. java中调用dll文件的两种方法

    https://www.cnblogs.com/huozhong/p/5830485.html JNA地址:http://blog.csdn.net/shendl/article/details/35 ...

  2. 天马行空W:在C++中调用DLL中的函数

    1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...

  3. 在C++中调用DLL中的函数

    1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...

  4. dll放在unity哪个文件夹下_unity中调用dll文件总结

    unity中调用dll文件总结 根据收集的资料,对unity中调用dll文件进行总结,目前常用的两种,在给出vs中封装dll文件的步骤. 一.调用c#中的dll文件 1.1封装dll文件 首先新建一个 ...

  5. java中调用 dll 动态库的简洁方法 JNative

    Java中调用DLL方法,是通过JNI接口实现的,http://www.ibm.com/developerworks/cn/java/l-linux-jni/ 这里有详细的说明.大概是先用Java写一 ...

  6. 一步一步学Silverlight 2系列(21):如何在Silverlight中调用JavaScriptjavascript

    一步一步学silverlight 2系列(21):如何在silverlight中调用javascript 概述 silverlight 2 beta 1版本发布了,无论从runtime还是tools都 ...

  7. 如何在Qt中调用activeX插件

    如何在Qt中调用ocx插件,介绍可用的两种方法. 先说第一种方法: 使用QAxObject,设置插件的classid后就可以调用插件的方法了. QAxObject *flash = new QAxOb ...

  8. excel调用python编程-如何在excel中调用python脚本

    如何在excel中调用python脚本 发布时间:2020-07-03 14:15:28 来源:亿速云 阅读:155 如何在excel中调用python脚本?针对这个问题,这篇文章详细介绍了相对应的分 ...

  9. 如何在MFC中调用CUDA

    如何在MFC中调用CUDA 有时候,我们需要在比较大的项目中调用CUDA,这就涉及到MFC+CUDA的环境配置问题,以矩阵相乘为例,在MFC中调用CUDA程序.我们参考罗振东iylzd@163.com ...

最新文章

  1. 人工智能改善客户服务体验
  2. xp用光盘安装linux系统安装教程视频,光盘重装xp系统图文教程
  3. 《强化学习周刊》第6期:强化学习应用之推荐系统
  4. CentOS安装jdk的三种方法
  5. 【Java 并发编程】线程池机制 ( 测试线程开销 | 启动线程分析 | 用户态 | 内核态 | 用户线程 | 内核线程 | 轻量级进程 )
  6. Pytorch基础(五)—— 池化层
  7. 即时通信软件开发的年轻开发者曾注意到
  8. Uva 10817 校长的烦恼
  9. mysql 管理工具—phpmyadmin docker 版使用
  10. Python3爬虫系列:理论+实验+爬取妹子图实战
  11. win10设置mysql环境变量
  12. playwright之贴吧签到
  13. 基于USB数据采集卡(DAQ)与IO模块的热电阻温度采集
  14. AI 编辑视频!这特效太逆天了!代码开源 SIGGRAPH Asia 2021
  15. PCB设计时如何选择合适的叠层方案
  16. Matlab App Designer编译打包exe后读取文件路径问题
  17. linux中文麻酱字_红糖麻酱卷的做法——Nice to meet you
  18. L2-039 清点代码库
  19. kali终端打不开以及msfconsole打不开
  20. 编程技巧│这些好用的网站,你千万别错过

热门文章

  1. mysql的聚合函数
  2. 直播盒子源码和直播盒子APP搭建教程详解
  3. python 列表 笛卡尔积_python-列表字典的笛卡尔积
  4. JNI Log 日志输出
  5. 计算机桌面变色怎么办,电脑屏幕变色是怎么回事
  6. git撤销单个文件的修改_git 撤销修改以及删除文件
  7. 关于《伤心者》,关于那些看不到结果的努力
  8. Faster R-CNN的RPN网络
  9. 传奇人物《周兴和》书连载24 感谢折磨你的人
  10. Windows 10 基于 IIS 搭建 GitLab