NodeJS和NW经由过程ffi挪用dll/so动态库

0x01. 运用的 npm 包

起首要装置 node-gyp, 用来从新编译依靠包。

npm instal -g node-gyp

然后重要用到下面三个包:

  • node-ffi — 运用Javascript挪用动态库

  • ref — 用来定义数据范例,供应指针功用

  • ref-array — 用Buffer来完成C语言中的 array 数据范例

npm install ffi   //这个敕令会同时装置上 ref、ref-struct
npm instal ref-array

0x02. 测试NODEJS挪用

要运用动态库中的函数,起首要对动态库里的函数举行声明。
比如在 Test.dll 库中,有两个函数以下:

void init(string name, int port);

string hello(int times);

js中举行声明的要领以下:

var ffi = require('ffi');
var Test = ffi.Library('Test.dll',{
    'init': ['void',['string','int']],
    'hello': ['string', ['int']]
});

#划定规矩就是  
'函数名':['返回值数据范例':['参数数据范例',...,'参数数据范例']]

声明完成后,就能够举行挪用了

Test.init('COM1', 9300);
Test.hello(5);

这里用简朴的数据范例,来说解挪用动态库的大抵流程。剩下比较复杂的处所在于怎样模仿像 指针构造体数组 等比较复杂的数据范例。

0x03. 构造体、指针、数组的转化

1. 构造体

构造体须要用到’ref-struct’这个包。假定有以下构造体:

typedef struct {
    byte UID[16];       /*餐盘标签 UID,16 进制*/
    byte UType[6];      /*餐盘范例,10 进制*/
    int ProdNo;         /*菜品编码,10 进制*/
    int ProdPrice;      /*菜品价钱,价钱以分为单元,10 进制*/
} DishInfo;

int范例的好办,能够直接运用 ref包里含有的范例 ref.types.int
UIDUType是两个bype范例的数组,须要运用ref-array举行模仿。

var refStruct = require('ref-struct');
var refArray = require('ref-array');

var DishInfo = refStruct({
    'UID': refArray('byte', 16),
    'UType': refArray('byte', 6),
    'ProdNo': ref.types.int,
    'ProdPrice': ref.types.int
});

2. 指针和援用

假定动态库中有函数以下, 第二个参数为构造体指针, 第三个参数是一个int 援用。

int Read(int port, DishInfo * pInfo, int &Count);

在声明函数的时刻,就须要指明指针和援用的数据范例。示例以下:

var ffi = require('ffi');
var ref = require('ref');
var refStruct = require('ref-struct');
var refArray = require('ref-array');

var DishInfo = refStruct({
    'UID': refArray('byte', 16),
    'UType': refArray('byte', 6),
    'ProdNo': ref.types.int,
    'ProdPrice': ref.types.int
});

//数据范例
var intPointer = ref.refType('int');
var DishInfoArrType = refArray(DishInfo);  //定义了DishInfo数组范例

var Test = ffi.Library('Test.dll',{
    'init': ['void',['string','int']],
    'hello': ['string', ['int']],
    'Read': ['int', ['int', DishInfoArrType, intPointer]]
});

//实例化
var count = ref.alloc('int');
var DishInfoArr = DishInfoArrType(3);

Test.Read(11, DishInfoArray, count);

//运用deref()猎取援用的现实值
var actualCount = count.deref();

0x04. NW 适配

运用NodeJS直接挪用没问题后,就能够运用 node-gyp 编译适配 NW 的包了, 这里只申明window环境下的运用要领。

1. 搭建编译环境

  1. 装置 Visual Studio 2015

    > ? [Windows Vista / 7 only] 须要装置 [.NET Framework 4.5.1](http://www.microsoft.com/en-us/download/details.aspx?id=40773)
    
  2. 装置 python 2.7 (不要装3.x.x,不支持),装完后运转

    npm config set python python2.7
  3. 设置visualstudio版本

    npm config set msvs_version 2015

2. 修正 win_delay_load.cc

翻开 Github – nw.js repository, 然后切换本身运用的nw 版本分支。
《NodeJS和NW经由过程ffi挪用dll/so动态库》

我这里挑选的是 nw14, 然后找到 tools/win_delay_load_hook.cc, 下载替换掉 %APPDATA%\npm\node_modules\node-gyp\src\win_delay_load_hook.cc

3. node-gyp 重编译 ffi 和 ref

# --target 输入nw 版本号,这里有用的是 v0.14.3, arch为 ia32 或许 x64

cd node_modules/ffi
node-gyp configure --target=0.14.3 --arch=ia32
node-gyp build

cd node_modules/ref
node-gyp configure --target=0.14.3 --arch=ia32
node-gyp build

0x05. 参考资料

  1. 经由过程ffi在node.js中挪用动态链接库(.so/.dll文件)

  2. Use Native Node Modules

  3. 恬不知耻加上本身的博客 XD

    原文作者:WensonSmith
    原文地址: https://segmentfault.com/a/1190000006826851
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞