最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Nodejs調(diào)用Dll模塊的方法

 更新時(shí)間:2018年09月17日 16:36:19   作者:蘇格團(tuán)隊(duì)  
這篇文章主要介紹了Nodejs調(diào)用Dll模塊的方法,在文中給大家提到了nodejs通過(guò)ffi調(diào)用dll模塊的代碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

公司項(xiàng)目采用Electron(electronjs.org/ )開(kāi)發(fā)pc應(yīng)用,會(huì)涉及到與底層硬件設(shè)備的通信,而sdk封裝 基本上都是通過(guò) C++ 動(dòng)態(tài)鏈接庫(kù)dll實(shí)現(xiàn)的。

有兩種方案可供選擇:

  • 方案一: 使用node-ffi
  • 方案二: 使用C++編寫(xiě)一個(gè)node addon,通過(guò)LoadLibrary調(diào)用dll

以上兩種方案都可以解決dll調(diào)用問(wèn)題,方案選型要個(gè)人對(duì)C++ 的掌握程度,如果熟悉C++開(kāi)發(fā),可以直接選擇方案二最方便。如果完全不了解C++,那么只能采用方案一。

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

二、什么是node-ffi?

www.npmjs.com/package/ffi

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

ffi究竟干了什么?其實(shí)它本質(zhì)上還是一個(gè)編譯后的Node addon,node_modules/ffi/build/Release/ffi_bindings.node, ffi_bindings.node就是一個(gè)addon ffi充當(dāng)了nodejs和dll之間的橋梁。

下面是一個(gè)簡(jiǎn)單的加載dll的demo實(shí)例:

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

如果本地沒(méi)有安裝編譯node addon的環(huán)境會(huì)報(bào)錯(cuò),如下圖所示

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

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

npm install node-gyp

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

總結(jié)來(lái)說(shuō)需要以下四點(diǎn):

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

NET Framework 4.5.1

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

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

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

electron-rebuild為多個(gè)版本的node和electron提供了一種簡(jiǎn)單發(fā)布預(yù)編譯二進(jìn)制原生模塊的方法。 它可以重建electron模塊,識(shí)別當(dāng)前electron版本,幫你自動(dòng)完成了下載 headers、編譯原生模塊等步驟。 一個(gè)下載 electron-rebuild 并重新編譯的例子:

npm install --save-dev electron-rebuild
# 每次運(yùn)行"npm install"時(shí),也運(yùn)行這條命令
./node_modules/.bin/electron-rebuild
# 在windows下如果上述命令遇到了問(wèn)題,嘗試這個(gè):
.\node_modules\.bin\electron-rebuild.cmd

詳情請(qǐng)看 electronjs.org/docs/tutori…

這里需要注意nodejs版本問(wèn)題,nodejs平臺(tái)必須跟dll保持一致,同樣是32位或者64位,如果兩者不一致,會(huì)導(dǎo)致調(diào)用dll失敗。

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

四、應(yīng)用舉例

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

首先我們來(lái)看一下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);
}

第一步:通過(guò)ffi注冊(cè)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方法,第一個(gè)參數(shù)傳入dll路徑,第二參數(shù)JSON對(duì)象配置相關(guān)接口。

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

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

1、基礎(chǔ)參數(shù)類(lèi)型bool, char, short, int, long等。

2、指針類(lèi)型,需要引入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,可以通過(guò)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ù)類(lèi)型配置與dll接口參數(shù)類(lèi)型配置相同,這里就不多說(shuō)。

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

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

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

var bool = sdkLib.CreateConnection();
console.log(bool); // true or false;
var cmd = 0, seq = 0, data = {...};
var dataStr = JSON.stringify(data);
// JavaScript中文字符長(zhǎng)度在C++中長(zhǎng)度計(jì)算要*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);

補(bǔ)充:下面看下NodeJS通過(guò)ffi調(diào)用DLL

第一步建立一個(gè)dll, 提供方法如下

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

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

npm install --save ffi

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

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

總結(jié)

以上所述是小編給大家介紹的Nodejs調(diào)用Dll模塊的方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Node.js實(shí)現(xiàn)大文件斷點(diǎn)續(xù)傳示例詳解

    Node.js實(shí)現(xiàn)大文件斷點(diǎn)續(xù)傳示例詳解

    這篇文章主要為大家介紹了Node.js實(shí)現(xiàn)大文件斷點(diǎn)續(xù)傳示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 淺談手寫(xiě)node可讀流之流動(dòng)模式

    淺談手寫(xiě)node可讀流之流動(dòng)模式

    這篇文章主要介紹了淺談手寫(xiě)node可讀流之流動(dòng)模式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • 詳解node.js平臺(tái)下Express的session與cookie模塊包的配置

    詳解node.js平臺(tái)下Express的session與cookie模塊包的配置

    本篇文章主要介紹了詳解node.js平臺(tái)下Express的session與cookie模塊包的配置,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-04-04
  • require加載器實(shí)現(xiàn)原理的深入理解

    require加載器實(shí)現(xiàn)原理的深入理解

    這篇文章主要給大家介紹了關(guān)于require加載器實(shí)現(xiàn)原理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • node.js中的buffer.Buffer.byteLength方法使用說(shuō)明

    node.js中的buffer.Buffer.byteLength方法使用說(shuō)明

    這篇文章主要介紹了node.js中的buffer.Buffer.byteLength方法使用說(shuō)明,本文介紹了buffer.Buffer.byteLength的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • 詳解node.js 下載圖片的 2 種方式

    詳解node.js 下載圖片的 2 種方式

    本文通過(guò)實(shí)例代碼給大家介紹了node.js 下載圖片的 2 種方式及下載遠(yuǎn)程圖片的實(shí)現(xiàn)代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2018-03-03
  • jenkins配置不同版本nodeJS保姆級(jí)教程

    jenkins配置不同版本nodeJS保姆級(jí)教程

    Jenkins確實(shí)是個(gè)好工具,今天在配置vue項(xiàng)目的時(shí)侯,看著別人配置好的東西,可是我就明明在配置時(shí),發(fā)現(xiàn)缺少node的版本選擇,這篇文章主要給大家介紹了關(guān)于jenkins配置不同版本nodeJS的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • async/await與promise(nodejs中的異步操作問(wèn)題)

    async/await與promise(nodejs中的異步操作問(wèn)題)

    這篇文章主要介紹了async/await與promise(nodejs中的異步操作問(wèn)題),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-03-03
  • 快速掌握Node.js環(huán)境的安裝與運(yùn)行方法

    快速掌握Node.js環(huán)境的安裝與運(yùn)行方法

    這篇文章主要介紹了Node.js環(huán)境的安裝與運(yùn)行方法,Node是基于Google Chrome V8引擎的JavaScript解釋器,需要的朋友可以參考下
    2016-02-02
  • Nodejs學(xué)習(xí)筆記之Global Objects全局對(duì)象

    Nodejs學(xué)習(xí)筆記之Global Objects全局對(duì)象

    本文是NodeJS學(xué)習(xí)筆記系列文章的第二篇,從這篇開(kāi)始我們就根據(jù)官方文檔來(lái)逐個(gè)學(xué)習(xí)下NodeJS的各個(gè)模塊,首先我們來(lái)學(xué)習(xí)下Global
    2015-01-01

最新評(píng)論

兴和县| 宜阳县| 特克斯县| 会泽县| 新宁县| 长兴县| 广宗县| 凭祥市| 洛浦县| 台山市| 鹤壁市| 扶沟县| 东安县| 兴业县| 永修县| 洪雅县| 朝阳区| 清河县| 建宁县| 巩留县| 高平市| 睢宁县| 英山县| 德兴市| 石首市| 东山县| 宿迁市| 苗栗县| 南城县| 平谷区| 商水县| 栾城县| 衡阳市| 陈巴尔虎旗| 沂源县| 台前县| 寻甸| 英德市| 武义县| 湘西| 定安县|