如何在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<object> 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#代碼試試。

廣州品牌設計公司https://www.houdianzi.com PPT模板下載大全https://redbox.wode007.com

遇到的問題

過程總是那么地不順利,即便知道了語法怎么寫也會出現一些問題,總結了下大概是以下幾種

  • win32 error 126 Dll文件的路徑寫錯了,或者Dll有相關的依賴,依賴沒有放在與入口Dll在同一級目錄下
  • win32 error 127 ffi定義的函數名、返回值類型或者參數類型與Dll定義的不一致
  • win32 error 193 Dll與當前的操作系統不匹配,當前系統是64位的Dll是32位的
  • 在Electron的項目使用edge無法編譯 edge是一個原生的模塊需要用你當前安裝node的版本重新編譯,重新編譯需要使用node-gyp,按下面幾步執行即可

    1. npm install -g node-gyp
    2. 安裝Python2.7和 Visual Studio Build Tools 或者VS2017
    3. npm config set msvs_version 2017
    4. node-gyp --python 你當前Python安裝的路徑
    5. cd node_modules/edge
    6. node-gyp configure
    7. node-gyp build
    8. 如果覺得麻煩可以直接使用electron-edge-js就不用自己重新編譯了,如果還是不行,就再裝一下electron-rebuild然后執行.\node_modules\.bin\electron-rebuild.cmd
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM