博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
nwjs ffi dll调用实现方案
阅读量:6081 次
发布时间:2019-06-20

本文共 3887 字,大约阅读时间需要 12 分钟。

nodejs ffi 调用dll 方法&过程

背景

Java 调用dll过程中 JNI的方式,存在隐患,dll经常挂掉,为此采用nodejs 调用dll进行封装

开发环境

  • win7 sp1 + nodejs 0.12.3 + python2.7 + vs2013

1.Win7 sp1 (x64操作系统)

  • Win7系统一定要是sp1的,没有sp1补丁自行到官网下载,sp1补丁(最好自己有系统盘,亲测安装补丁过程比安装系统还慢)
  • 如果这个补丁没有更新是装不上Visual Studio 2013的,还是乖乖的用这个版本吧。 (个人使用版本经历,让人泪奔 vs2015 —— vs2017 —— vs2013)

2.Visual Studio 2013

  • 提供基础的编译环境,nodejs modules在重新编译的时候需要依赖它
  • 上面已经说了,老老实实安装吧!!!

3.Python 2.7.6

  • 提供基础的编译环境,nodejs modules在重新编译的时候需要依赖它
  • 下载地址 :

4.nodeJS 0.12.3

  • 一般dll文件都是32位的,ffi调用时需要使用32位版本的nodejs
  • 下载地址: 文件是msi格式,直接安装即可,环境变量自动配好不用管。

5.nwjs 0.12.3

  • 为保证程序可以在xp下使用不是使用太高的版本我选择了0.12.3版本
  • 下载地址:

开始动手

1.打开DOS界面,安装nw-gyp执行下面的命令:
npm install nw-gyp -g
2.设置vs版本:
npm config set msvs_version 2013 --global (2013是visual studio的版本,你也可以尝试其他版本,我是放弃了)

1.新建一个项目文件夹,创建index.html和package.json文件:

(测试是用的windows系统里的消息窗口dll文件)

<html lang="en">

<head>

nwjs call DLL

</head>

<body>
<script type="text/javascript">

var FFI = require('ffi');   function TEXT(text){      return new Buffer(text, 'ucs2').toString('binary');   }   var user32 = new FFI.Library('user32', {      'MessageBoxW':       [         'int32', [ 'int32', 'string', 'string', 'int32' ]      ]   });   var OK_or_Cancel = user32.MessageBoxW(      0, TEXT('I am Node.JS!'), TEXT('Hello, World!'), 1   );   console.log(OK_or_Cancel);

</script>

</body>
</html>

package.json

{
"name": "test",
"version": "1.0.1",
"main": "index.html",
"webkit":{

"plugin" : true

}

}

注意package.json文件里需要添加webkit属性来说明你需要调用第三方包。

2.DOS界面下进入项目文件夹,安装ffi和ref:
npm install ffi
npm install ref
3.编译ffi和ref模块,因为ffi中包含ref所以先编译ref再编译ffi,依次的命令如下:
进入'项目目录node_modulesffinode_modulesref',执行nw-gyp rebuild --target=0.12.3
(0.12.3是你的nwjs版本,如果不是这个版本改为你自己的即可)
进入'项目目录node_modulesffi',执行nw-gyp rebuild --target=0.12.3
4.最后在你的项目文件夹下将所有文件打包为zip格式,将zip文件拖进node-webkit目录下的nw.exe文件上执行即可。
5.看到界面上弹出“I am Node.JS!”说明成功了!

参考:

提示:

1.由于ffi模块是为C语言的dll包服务的,所以在编写的dll的C++源代码时必须要有 extern “C” 来修饰。例如在你的c++代码里需要这样声明函数才能有效(在.h文件中声明时使用):
extern "C" DLLSERVER_API int sumInDll(int n1, int n2);
2.ffi在使用时需要匹配对应的环境,如果是32位dll文件,那么在安装nodeJS,python和nwjs都需要用对应的32位版本;如果是64位dll文件,则对应的软件都需要是64位的;
3.ffi在用的时候还是挺方便的,只要环境匹配对就可以。唯一的麻烦是它需要对源dll代码声明时进行修改,这个就不如addon一劳永逸了。所以如果引用的dll文件比较多,或者是引入第三方dll文件,ffi的方法就不可取。

遇到问题列表

1、winxp 系统下dll错误

nodejs的ffi库是一个非常好用的调用dll的库,尤其是在使用nwjs进行桌面应用开发的时候。
安装、编译、使用ffi库的方法比较简单,网上也有很多教程,但是当我们在win7或者更高的Windows系统中编译好了ffi模块,开发好了应用后会发现在Windows XP上无法require我们的ffi,及时将编译好的ffi_bindings.node单独require也无法使用,require的时候会出现“Error: The specified procedure could not be found”的错误。
经过几天的研究,终于找到了解决方案。在能够正常编译和引用ffi的Windows系统上,进入ffi文件夹中的src文件夹,找到文件“win32-dlfcn.cc”,并将里面的地96行和第99行的两行代码(我是用的ffi版本为2.2.0,其他版本还没有确定是不是这两行),对应的代码应该是:

errorMode = GetErrorMode();

SetErrorMode(errorMode | SEM_FAILCRITICALERRORS);

将这两行代码注释掉,然后在从命令行进入到ffi根目录,执行“node-gyp rebuild”命令(或者“nw-gyp rebuild”命令,如果想要在nwjs中使用),编译出来的ffi库就可以在Windows XP上正常使用了。

参考文章:

2、nodejs 读取中文乱码问题 (iconv-lite)

var ref = require("ref");

var ffi = require("ffi");
var iconv = require('iconv-lite');
var DLL = new ffi.Library('sample.dll', {
'readData': ['int', ['string', 'string']],
'sendMsg': ['string', ['string', 'string']]
});

module.exports = {

sendMsg: function(sendMsg){    var maxRTNNameLength = 4096;    var rtnRef = new Buffer(maxRTNNameLength);    console.log("send:",sendMsg);    var rtn = DLL.sendMsg(sendMsg, rtnRef);    var as_data = iconv.decode(rtnRef, 'GBK');//解码成utf8.    var userbuffer = iconv.encode(as_data, 'gbk');//utf8数据编码成gbk    var as_data = iconv.decode(rtnRef, 'GBK');//解码成utf8.    return as_data;},readData:function(){    var maxIdCardLength = 19;    var idCardRef = new Buffer(maxIdCardLength);    var maxNameLength = 31;    var nameRef = new Buffer(maxNameLength);    if (DLL.readData(idCardRef, nameRef) == 0) {        var name = ref.readCString(nameRef, 0);        var card = ref.readCString(idCardRef, 1);        return {name: name, card: card};    }}

}

经过几天的努力完成了程序的调用,该遇到的问题基本都遇到了,希望本篇文章对大家有帮助!

转载地址:http://ayagx.baihongyu.com/

你可能感兴趣的文章
这些代码都是 吃屁的,
查看>>
bundle id
查看>>
用shell统计表格数据
查看>>
iproute2+tc notes
查看>>
【PythonChallenge】Level 5
查看>>
OpenCV合成视频
查看>>
魔幻般冒泡背景的CSS3按钮动画
查看>>
Leetcode: Median of two sorted Array
查看>>
MySQL常见报错汇总
查看>>
Zuul 网关搭建
查看>>
合并两个有序链表
查看>>
[HDU2222] Keywords Search
查看>>
射极跟随器的设计及参数确定
查看>>
电脑硬盘空间怎么越来越小
查看>>
android SystemUI导入eclipse 编译
查看>>
架构师速成-架构体系
查看>>
用minGW编译ffmpeg(供替换opencv中引用的ffmpeg库)
查看>>
MySQL多实例配置
查看>>
Nginx 一个高性能的HTTP和反向代理服务器
查看>>
IT男剁手指南:花钱也是一门大学问
查看>>