最近项目上用到electron,需要实现与仪器对接功能,目前很多仪器都是串口通讯的。因此需要编写Dll实现与硬件串口的访问。作为Delphi多年编写的Coder,当然首选用Delphi来实现了。
思路:使用Delphi编写DLL实现与串口通讯,发送串口指令,当串口返回数据后,通过Delphi回调electron方法,返回串口数据。
经过多轮反复调试和躺过n个坑后,终于搞定,先分享大家:
1、Delphi DLL 代码:
interface
type
TMethodCallback = function(s: PChar):Integer; cdecl;
function setMethod(Callback: TMethodCallback):Integer; stdcall;
implementation
function setMethod(Callback: TMethodCallback):Integer;
begin
Result:=0;
if Assigned(Callback) then
begin
Callback('hello,electron-callBack!');
Result:=1;
end;
end;
特别注意:TMethodCallback ,electron 回调函数形式,必须声明为:cdecl。Delphi与C语言系列内存访问释放的约定顺序。 开始我用的是stdcall,虽然能够被回调,但是每次回调electron方法后,会立即崩溃。
总结:delphi的DLL方法被调用,需要使用stdcall。调用C系列语言的方法必须使用cdecl。
2、electron 代码:
import ffiNapi from 'ffi-napi'
import fs from 'fs'
const dllPath = path.join(__dirname, app.isPackaged ? '../../dll/' : '../dll/')
// 测试dll加载
const testDllPath = dllPath + 'test/Serial_D.dll'
let testDll = undefined
if (fs.existsSync(testDllPath)) {
testDll = ffiNapi.Library(testDllPath, { setMethod: ['int32', ['pointer']] })
}
function abc(str) {
console.log(str)
}
let callback = ffiNapi.Callback('int32', ['string'], abc)
ipcMain.on('electron-win-dll-test', event => {
if (testDll) {
testDll.setMethod(callback)
}
event.returnValue = true
})
注意:
回调函数声明为:pointer。
electron要使用32位的环境,因为很多硬件自带驱动DLL都是32位的,如果使用64位环境会直接报错。