electron
node-ffi 调用dll
var FFI = require ( 'ffi' );
var ref = require ( 'ref' );
var Struct = require ( 'ref-struct' );
var refArray = require ( 'ref-array' );
1、根据参数类型声明函数。
char* => string //也可以直接用 char *
int* => ref.refType('int') //也可以直接用 int *
struct *=>ref.refType(liv_hardware_info)
struct[] *=> ref.refType(liv_hardware_info,3) //结构体数组
VOID * => ref.refType('pointer')
结构体中的参数:
char* [] => refArray('byte', 8)
基本类型
基本类型已经定义在了ref.types里,可以直接使用类型字符串或者’ref.types’中的类型对象。而对于枚举类型,简单当作int或者uint处理就可以了。
指针
对于指针类型,简单类型可以直接在参数列表里写int *,pointer这样的,生成类型的指针可以用ref.refType(type)。在调用函数时,执行var vRef = ref.alloc(type)得到一个引用对象,将对象传入函数即可。需要获取vRef指向的值v可以用var v = ref.deref(vRef)。对字符串类型的buffer可能需要使用ref.readCString(buffer)来读取(它可以处理末尾的’\0’)。
实例
var intPtr = ref.refType ( 'int' );
var iv_hardware_info = Struct ({
'developernumber' : 'int' ,
'serialnumber' : refArray ( 'byte' , 8 ),
'manufacturedate' : 'int'
});
let zm2007 = new FFI . Library ( "./dll/zm_2007.dll" , {
'DesEnCodeHex' : [ 'int' , [ 'string' , 'string' , 'string' ]],
'DesDeCodeHex' : [ 'int' , [ 'string' , 'string' , 'string' ]],
'LIV_open' : [ 'int' , [ 'int' , 'int' , intPtr ]],
'LIV_get_hardware_info' : [ 'int' , [ 'int' , ref . refType ( liv_hardware_info ) ]]
});
2、调用方法
var handleRef = ref . alloc ( 'int' );//预先分配int 指针空间
let li_rtn = zm2007 . LIV_open ( 0 , 0 , handleRef )
ll_handle = handleRef . deref ();//获取int值
var lt = new Buffer ( 512 ). fill ( " " );
zm2007 . DesEnCodeHex ( st , '770814' , lt );
let ls_out = lt . toString ( "ascii" ); //buffer中即为传出参数
var liv_info = new liv_hardware_info ();//结构体初始化
zm2007.LIV_get_hardware_info ( ll_handle , liv_info.ref());//调用
const buf = Buffer.from ( liv_info.serialnumber ); //获取已生成结构体中属性数据。
补充一点:字符集引起的中文乱码问题
默认node.js是utf8字符串,而我们的dll很多都是gbk编码,从参数的传入需要转成gbk
转码一般用这个模块,纯js版本
var iconv = require ( 'iconv-lite' );
var infoRef = new Buffer ( 512 ); //调用函数预先分配空间
//开始调用。infoRef中是dll返回的gbk 数据串。
var as_data = iconv . decode ( infoRef , 'GBK' ) ;//解码成utf8.
var userbuffer = iconv . encode ( as_data , 'gbk' );//utf8数据编码成gbk