怎么在Nodejs中調(diào)用Dll模塊

這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)怎么在Nodejs中調(diào)用Dll模塊,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

專業(yè)領(lǐng)域包括網(wǎng)站建設(shè)、網(wǎng)站制作、商城網(wǎng)站制作、微信營銷、系統(tǒng)平臺開發(fā), 與其他網(wǎng)站設(shè)計及系統(tǒng)開發(fā)公司不同,創(chuàng)新互聯(lián)建站的整合解決方案結(jié)合了幫做網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗和互聯(lián)網(wǎng)整合營銷的理念,并將策略和執(zhí)行緊密結(jié)合,為客戶提供全網(wǎng)互聯(lián)網(wǎng)整合方案。

有兩種方案可供選擇:

  • 方案一: 使用node-ffi

  • 方案二: 使用C++編寫一個node addon,通過LoadLibrary調(diào)用dll

什么是node-ffi?

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

ffi究竟干了什么?其實它本質(zhì)上還是一個編譯后的Node addon,node_modules/ffi/build/Release/ffi_bindings.node, ffi_bindings.node就是一個addon ffi充當(dāng)了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的環(huán)境會報錯,如下圖所示

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

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

npm install node-gyp

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

總結(jié)來說需要以下四點:

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

NET Framework 4.5.1

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

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

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

electron-rebuild為多個版本的node和electron提供了一種簡單發(fā)布預(yù)編譯二進制原生模塊的方法。 它可以重建electron模塊,識別當(dāng)前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位,如果兩者不一致,會導(dǎo)致調(diào)用dll失敗。

成功安裝ffi模塊之后,就可以開始我們下面的ffi調(diào)用dll的實例應(yīng)用。

四、應(yīng)用舉例

在開發(fā)需求中,需要調(diào)用基于C++編寫的TCP數(shù)據(jù)轉(zhuǎn)發(fā)服務(wù)的SDK。

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

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

ffi調(diào)用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方法,第一個參數(shù)傳入dll路徑,第二參數(shù)JSON對象配置相關(guān)接口。

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

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

1、基礎(chǔ)參數(shù)類型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、回調(diào)函數(shù)指針pointer,可以通過ffi.Callback創(chuàng)建,如下:

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

回調(diào)函數(shù)參數(shù)類型配置與dll接口參數(shù)類型配置相同,這里就不多說。

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

第二步:接口調(diào)用

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

var bool = sdkLib.CreateConnection();
console.log(bool); // true or false;
var cmd = 0, seq = 0, data = {...};
var dataStr = JSON.stringify(data);
// JavaScript中文字符長度在C++中長度計算要*3
sdkLib.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調(diào)用DLL

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

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

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

npm install --save ffi

第三步創(chuàng)建測試文件

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

上述就是小編為大家分享的怎么在Nodejs中調(diào)用Dll模塊了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁標(biāo)題:怎么在Nodejs中調(diào)用Dll模塊
網(wǎng)站網(wǎng)址:http://muchs.cn/article8/gdegop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)品牌網(wǎng)站設(shè)計、服務(wù)器托管App開發(fā)、網(wǎng)站維護網(wǎng)站設(shè)計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)