国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > JS > 正文

Nodejs調用Dll模塊的方法

2024-05-06 16:46:09
字體:
來源:轉載
供稿:網友

公司項目采用Electron(electronjs.org/ )開發pc應用,會涉及到與底層硬件設備的通信,而sdk封裝 基本上都是通過 C++ 動態鏈接庫dll實現的。

有兩種方案可供選擇:

  • 方案一: 使用node-ffi
  • 方案二: 使用C++編寫一個node addon,通過LoadLibrary調用dll

以上兩種方案都可以解決dll調用問題,方案選型要個人對C++ 的掌握程度,如果熟悉C++開發,可以直接選擇方案二最方便。如果完全不了解C++,那么只能采用方案一。

由于筆主不太懂C++,最終選擇第一種方案。

二、什么是node-ffi?

( www.npmjs.com/package/ffi

node-ffi是使用純JavaScript加載和調用動態庫的node addon,它可以用來在不寫任何C++代碼的情況下調用動態鏈接庫的API 接口。

ffi究竟干了什么?其實它本質上還是一個編譯后的Node addon,node_modules/ffi/build/Release/ffi_bindings.node, ffi_bindings.node就是一個addon ffi充當了nodejs和dll之間的橋梁。

下面是一個簡單的加載dll的demo實例:

var ffi = require('ffi');var libpath = path.join(_dirname, '/test.dll');var testLib = ffi.Library(libpath, { 'start': ['bool', ['bool']]});testLib.start(true); // true

三、安裝node-ffi

npm install ffi

如果本地沒有安裝編譯node addon的環境會報錯,如下圖所示

無論是使用ffi,還是直接寫node addon,都缺少不了編譯node Addon這個步驟,要編譯node addon,有兩種方法:

1、node-gyp( www.npmjs.com/package/nod … )。

npm install node-gyp

具體安裝參考:github.com/nodejs/node…

總結來說需要以下四點:

python 2.7-3.0版本之間 (推薦裝v2.7,v3.x.x是不支持的)

NET Framework 4.5.1

Visual C++編譯工具 (在windows中是不需要安裝VS,如果自己安裝例如VS2015,導致編譯報錯error MSB4132: The tools version "2.0" is unrecognized. Available tools versions are "4.0".這個問題,說明沒有裝好編譯器,又或者編譯器沒有被正確地識別, node-gyp的文檔建議使用npm config set msvs_version 2015, 但是有些機器即使這樣設置了也無效,需要手動設置msvs_version, 應該這樣寫: node-gyp rebuild --msvs_version=2015。如果因為安裝了VS2015導致無法正常編譯,可直接恢復到安裝VS之前的還原點)
環境變量配置。(注:python安裝位置需要添加到環境變量)

2、electron-rebuild( www.npmjs.com/package/ele… )

如果采用electron開發應用程序,electron同樣也支持node原生模塊,但由于和官方的node 相比使用了不同的 V8 引擎,如果你想編譯原生模塊,則需要手動設置electron的headers的位置。

electron-rebuild為多個版本的node和electron提供了一種簡單發布預編譯二進制原生模塊的方法。 它可以重建electron模塊,識別當前electron版本,幫你自動完成了下載 headers、編譯原生模塊等步驟。 一個下載 electron-rebuild 并重新編譯的例子:

npm install --save-dev electron-rebuild# 每次運行"npm install"時,也運行這條命令./node_modules/.bin/electron-rebuild# 在windows下如果上述命令遇到了問題,嘗試這個:./node_modules/.bin/electron-rebuild.cmd

詳情請看 electronjs.org/docs/tutori…

這里需要注意nodejs版本問題,nodejs平臺必須跟dll保持一致,同樣是32位或者64位,如果兩者不一致,會導致調用dll失敗。

成功安裝ffi模塊之后,就可以開始我們下面的ffi調用dll的實例應用。

四、應用舉例

在開發需求中,需要調用基于C++編寫的TCP數據轉發服務的SDK。

首先我們來看一下dll頭文件接口聲明的代碼如下:

#ifndef JS_CONNECTION_SDK#define JS_CONNECTION_SDK#ifdef JS_SDK#define C_EXPORT __declspec(dllexport)#else#define C_EXPORT __declspec(dllimport)#endifextern "C"{  typedef void(*ReceiveCallback) (int cmd, int seq, const char *data);  /*設置讀取數據回調*/  C_EXPORT void _cdecl SetReceiveCallback(ReceiveCallback callback);  /*  *設置option  */  C_EXPORT void _cdecl SetOption(    const char* appKey,     const char* tk,    int lc,     int rm  );  /*  *創建連接  */  C_EXPORT bool _cdecl CreateConnection();  /*發送數據*/  C_EXPORT bool _cdecl SendData(int cmd, int seq, const char *data, unsigned int len);  /*釋放連接*/  C_EXPORT void _cdecl ReleaseConnection();}#endif

ffi調用dll模塊封裝,代碼如下:

try { const ffi = require('ffi'); const path = require('path'); const Buffer = require('buffer').Buffer; const libpath = path.join(APP_PATH, '..', '..', '/testSDK.dll');  const sdkLib = ffi.Library(libpath, { 'CreateConnection': ['bool', []], 'SendData': ['bool', ['int', 'int', 'string', 'int']], 'ReleaseConnection': ['void', []], 'SetOption': ['void', ['string', 'string', 'int', 'int']], 'SetReceiveCallback': ['void', ['pointer']] });  module.exports = { createConnection: function(){  sdkLib.CreateConnection(); }, setReceiveCallback(cb) {  global.setReceiveCallback = ffi.Callback('void', ['int', 'int', 'string'], function(cmd, seq, data){  cb && cb(cmd, seq, data && JSON.parse(data));  });  sdkLib.SetReceiveCallback(global.setReceiveCallback); }, sendData: function(cmd, seq, data){  data = JSON.stringify(data);  sdkLib.SendData(cmd, seq, data, data.replace(/[^/x00-/xff]/g, '000').length, 0); }, releaseConnection: function(){  sdkLib.ReleaseConnection(); }, setOption: function (option) {  sdkLib.SetOption(  option.appKey,  option.tk,  option.lc,  option.rm  ); } } } catch (error) { log.info(error);}

第一步:通過ffi注冊dll接口

const sdkLib = ffi.Library(libpath, { 'CreateConnection': ['bool', []], 'SendData': ['bool', ['int', 'int', 'string', 'int']], 'ReleaseConnection': ['void', []], 'SetOption': ['void', ['string', 'string', 'int', 'int']], 'SetReceiveCallback': ['void', ['pointer']] }); 

ffi.Library方法,第一個參數傳入dll路徑,第二參數JSON對象配置相關接口。

key對應dll頭文件中輸出的接口,例如C_EXPORT bool _cdecl CreateConnection();

value array配置參數類型,array[0]注冊接口函數返回值類型,array[1]注冊接口函數傳入形參類型。

1、基礎參數類型bool, char, short, int, long等。

2、指針類型,需要引入ref模塊,如下:

var ref = require('ref');var intPointer = ref.refType('char');var doublePointer = ref.refType('short');var charPointer = ref.refType('int');var stringPointer = ref.refType('long');var boolPointer = ref.refType('bool');

3、回調函數指針pointer,可以通過ffi.Callback創建,如下:

global.setReceiveCallback = ffi.Callback('void', ['int', 'int', 'string'], function(cmd, seq, data){ cb && cb(cmd, seq, data && JSON.parse(data)); });sdkLib.SetReceiveCallback(global.setReceiveCallback);

回調函數參數類型配置與dll接口參數類型配置相同,這里就不多說。

這里需要注意一點,回調函數可能會被JavaScript垃圾自動回收機制回收,所以我這里是把回調函數掛載到全局對象global上。

第二步:接口調用

通過ffi.Library(libpath, {...})注冊接口,可以直通過返回的sdkLib對象調用對接的接口。例如:

var bool = sdkLib.CreateConnection();console.log(bool); // true or false;var cmd = 0, seq = 0, data = {...};var dataStr = JSON.stringify(data);// JavaScript中文字符長度在C++中長度計算要*3sdkLib.SendData(cmd, seq, data, data.replace(/[^/x00-/xff]/g, '000').length);global.setReceiveCallback = ffi.Callback('void', ['int', 'int', 'string'], function(cmd, seq, data){ cb(cmd, seq, data && JSON.parse(data));});sdkLib.SetReceiveCallback(global.setReceiveCallback);

補充:下面看下NodeJS通過ffi調用DLL

第一步建立一個dll, 提供方法如下

int WINAPI CAM_Open(char *pIn, char* pOut);

第二步安裝ffi (前提已安裝python2.x環境)

npm install --save ffi

第三步創建測試文件

var ffi = require("ffi")var DLL = ffi.Library('FaceRecognition.dll', {  'CAM_Open' : ['int', ['string', 'string']]});var result = DLL.CAM_Open("", "");console.log(result)

參考資料

https://github.com/node-ffi/node-ffi

總結

以上所述是小編給大家介紹的Nodejs調用Dll模塊的方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網網站的支持!


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永清县| 金坛市| 康乐县| 江西省| 环江| 紫金县| 宜君县| 禄丰县| 蓝山县| 邵武市| 广昌县| 廊坊市| 涟源市| 饶河县| 白水县| 崇仁县| 上蔡县| 孝感市| 曲沃县| 大方县| 加查县| 安达市| 革吉县| 榆社县| 永顺县| 普陀区| 清新县| 黑河市| 龙门县| 北宁市| 乌拉特后旗| 靖远县| 河津市| 广东省| 大连市| 察哈| 香河县| 柳河县| 镇远县| 冀州市| 九龙坡区|