ffi介绍:

node-ffi是一个用于使用纯JavaScript加载和调用动态库的Node.js插件。它可以用来在不编写任何C++代码的情况下创建与本地DLL库的绑定。同时它负责处理跨JavaScript和C的类型转换。

node-ffi连接了C代码和JS代码, 通过内存共享来完成调用, 而内部又通过ref,ref-array和ref-struct来实现类型转换。

一、环境安装、配置

1、以管理员权限打开cmd,输入快捷命令:npm install --global --production windows-build-tools

这期间可能会遇到visual studio(C++工具包)安装不成功的情况:

这种情况下可以使用离线安装的方式(通过以下链接下载离线安装包):

https://pan.baidu.com/s/1Nh7cCrqyroEMH90HUYbvfw   提取码:5251

直接安装:

安装完成之后查看python是否安装成功:

 这说明安装成功,安装成功之后将python的路径添加到环境变量中:

2、安装.net环境地址(可以选择4.6.2包)

.NET SDKs downloads for Visual Studio

3、安装上述各环境之后就可以安装ffi了,我这边安装的ffi版本是2.3.0的,使用命令

cnpm install ffi@2.3.0,相对应类型转换的插件版本如下:

"ffi": "^2.3.0",

"ref": "^1.3.5",

"ref-array": "^1.2.0",

"ref-struct": "^1.1.0",

4、安装上述环境的过程中遇到了很多问题,捣鼓了很久才把整个环境安装好,环境安装好之后调用动态库的过程也遇到很多问题,下面记录下自己在安装和调用的过程中遇到的一些问题:

(1)报语法错误:

上面的截图说是啥语法错误,在网上找了很多资料,很多说是因为nodejs版本高了的问题,于是我将nodejs版本降低,降低到了v11.10.0,然后再安装,最后成功了:

(2)font.scss报错:

上面截图的错误可以通过提示重新安装一遍sass,命令如下:

npm rebuild node-sass

(3)Error:Cannot find module 'ffi'

上面的提示需要重新安装一遍ffi

(4)Error: A dynamic link library (DLL) initialization routine failed

上面报错问题需要执行下面的命令重新rebuild:

1、npm config set python "C:\Python27\python.exe"

2、npm config set node_gyp "C:\Users\10376\AppData\Roaming\npm\node_modules\node-gyp\bin\node-gyp.js"

3、重新编译electron:./node_modules/.bin/electron-rebuild

4、.\node_modules\.bin\electron-rebuild.cmd

(5)调用动态库时报各种编码错误:

Uncaught Error: Dynamic Linking Error: Win32 error 126

DLL引用的路径错误,检查下DLL的路径是否正确(因为项目中调用的动态库比较多,出现有的用下面的方式写可以正常调用,但是有的动态库必须放在本机安装的nodejs的目录下,具体原因没摸清楚,猜测是因为C++打包或配置的问题,不同的包引入方式不同)

// 正确示例
let DllA = path.resolve(__dirname, '../../../xxx/xxxx.dll')// 生产环境
if (process.env.NODE_ENV !== 'development') {DllA = path.resolve(__dirname, '../../../../xxx/xxx' + arch + '.dll')DllB = path.resolve(__dirname, '../../../../xxx/xxxx.dll')
}

Uncaught Error: Dynamic Linking Error: Win32 error 193

DLL位数不对,根据系统来确定使用x86还是x64,可通过os进行判断引入相应的DLL

// 正确示例
const arch = os.arch() === 'x64' ? 'x64' : 'x86'
let DllA = path.resolve(__dirname, '../../../xxx/xxx' + arch + '.dll')
if (process.env.NODE_ENV !== 'development') {DllA = path.resolve(__dirname, '../../../../xxx/xxx' + arch + '.dll')
}

Uncaught Error: Dynamic Linking Error: Win32 error 127

DLL没有对应的函数或函数定义错误,可以使用函数查看器进行查看

DLL错误,比如系统的一些DLL可以直接进行引用或者还需要引用其他的DLL文件(如: 引入A,但是A需要引入B)
函数查看器下载地址

// 正确示例
const User32 = ffi.Library('user32.dll', {GetTopWindow: ['long', ['long']],GetWindowThreadProcessId: ['int', ['long', 'int']],GetForegroundWindow: ['long', []],IsHungAppWindow: ['bool', ['long']]
})

二、ffi调用C++动态库语法详解

变量类型:C语言中有4种基础数据类型(整型  浮点型  指针  聚合类型)

1、整形、字符型都有分有符号和无符号两种。

在不声明unsigned时,默认为signed型

ref中unsigned会缩写成u,如uchar对应unsigned char

浮点型中有float  double  long

2、项目中使用:

(1)插件引入

(2)调用C++方法初始化

C++定义的原始方法如下:

1、初始化第三方
int  BS_Init3(char *IP, short port, unsigned short SysCode, unsigned short TerminalNo)

2、初始化读卡器
int BS_CRInit()

3、关闭读卡器
bool BS_CRClose()

4、快速读卡号

int BS_FastGetCardNo(unsigned int *CardNo)

5、读卡,返回余额和学号
int BS_ReadCard(int *Balance, char *StudentCode)

6、消费,传入消费金额TranAmt(以分为单位的正整数),返回卡片消费后的余额Balance
int BS_Consume(int TranAmt, int *Balance)

上述中new ffi.Library就是ffi调用C++的方法,第一个参数是动态库的位置,第二个参数是调用动态库的方法,类型通过ref相关插件进行转换。

主要需要注意的就是4、5、6方法中的指针类型,CardNo、Balance和StudentCode需要转换成指针类型,调用的时候会通过这个变量将值写入返回给我们。

(3)方法调用

调用1初始化方法,只需要将值传入看返回值是否初始化成功就可以了

调用2方法:

调用3方法:

调用4方法,这里需要注意的就是CardNo,它是个指针类型,需要通过ref.alloc()方法定义一个变量,用于接收动态库给的值,拿到值之后通过ref.deref()的方法转换一下,其实ref就相当于一个语言转换器,先将我们的语言转换成C++可以识别的,拿到值之后再转换成js可以识别的。

 调用5、6,这里与上面不用的是*char类型的处理方式

3、项目中语法使用过程中遇到的问题记录(复杂结构体的调用)

结构体指针类型,结构体只有输入值的可以正常调用成功,但是当结构体中有些字段需要前端传递值,有些字段是C++动态库返回的值的情况下,每次调用的都不成功,具体如下:

结构体定义:

结构体初始化:

结构体调用:

上述调用的过程中每次返回给我的错误信息都是交易额错误,也就是二进制的-0000000001怎么转换也传不过去,问了java的开发人员都说没有这种值得处理方式,其实在C++中就是将这个值塞到内存地址中,然而我在nodejs中用啥方法也不行,最后迫于无赖只能让动态库得开发人员重新封装,将调用得方法传参改得简洁一点。

如果有大佬实现过这种复杂得结构体调用可以一起探讨!!!

nodejs ffi调用C++dll动态库 ffi调用语法相关推荐

  1. java调用c so动态库_jni 调用C动态库dll/so

    http://hi.baidu.com/fengying765/blog/item/7081113e5fde53e555e7233f.html 作为主调方的Java源程序TestJNI.java如下. ...

  2. Node.js 调用 dll动态库 以华旭身份证阅读器为例

    需求来源 由于使用Electron使用开发桌面端,同时也需要连接硬件设备,单纯使用js方法无法完成,需要通过Node调用dll动态库方式完成. 版本说明: node v12.18.3 (32位) np ...

  3. C++中.lib静态库、.dll动态库的生成及调用2

    关于动.静态库的介绍及静态库的生成及调用参见:C++中.lib静态库..dll动态库的生成及调用<1>,本文主要介绍基于VS2015平台的动态库dll的生成及调用方法. 一.动态库的生成 ...

  4. C++中.lib静态库、.dll动态库的生成及调用1

    一.前言 1.动态链接库(dll)与静态链接库(lib): 动态链接库(dll)是一个可以被其他应用程序共享的程序模块,其中封装了一些可以被共享的例程和资源.在链接步骤中,连接器将从库文件取得所需的代 ...

  5. JNA框架调用dll动态库(给你整得明明白白)

    java调用dll动态库的方法,总的有三种:JNI.JNA.JNative.其中JNA调用DLL是最方便的.网上文章一大堆,我就不废话了. 使用JNA框架调用DLL动态库,步骤如下: 一.环境准备 1 ...

  6. java 动态库_java调用dll动态库文件的一般总结

    前一段时间,在项目需求中,需要调用一下第三方的动态库文件,下面是本人一些尝试的经历. 首先需要明白的是,在java中是不能直接调用动态库文件的,因为动态库文件是使用c或是c++编写的,作为一种跨   ...

  7. C#调用C/C++动态库dll异常:对 PInvoke 函数调用导致堆栈不对称问题

    结论:如果你是用C#调用C的动态库,如果出现"对 PInvoke 函数调用导致堆栈不对称问题",建议优先调整CallingConvention的值,建议改为CallingConve ...

  8. C#总结:C#调用C++的动态库Dll遇到的问题[动态库调用/结构体指针调用/union共同体定义]

    记录使用C#调用C++的生成的DLL手柄键盘驱动库包括****.sys(驱动文件)和****.dll(库文件)的全部问题. C#调用C++的库有两种:静态调用和动态调用 静态调用,使用.net 提供的 ...

  9. C# VC6调用VC6的动态库DLL

    C# VC6调用VC6的动态库DLL 一 VC创建动态库 1. DLL的创建 启动VC6.0, 新建一个"Win32 Dynamic-Link Library"工程,选择" ...

  10. Windows系统下通过JNI调用dll动态库的实现

    目的:java代码使用jni获取数据 工具: eclipse + Microsoft visual studio (c++) 业务代码: Java代码业务实现: package com.weip.jn ...

最新文章

  1. Service Mesh — Overview
  2. Appium+PythonUI自动化之webdriver 的三种等待方式(强制等待、隐式等待、显示等待)
  3. 差分进化算法_基于差分进化的水泥烧成系统动态优化算法
  4. JavaScript正则表达式的坑很深
  5. (二)线程--通过委托异步调用方法
  6. ActiveMq工作笔记003---SpringBoot集成ActiveMq_随时更新
  7. iirf有时有效,有时返回404错误的解决方法
  8. bzoj 2555: SubString
  9. c语言getch函数_在C / C ++中使用getch()函数
  10. qq手机令牌 for android3.3 官方安装版,原QQ安全助手|QQ手机管家 for Android 安卓版v3.3.0 - PC6安卓网...
  11. vbs基础教程(1)
  12. 中文文本情感分析:基于机器学习方法的思路
  13. google 常用的技术搜索关键词
  14. stata陈强:第四章 stata操作基础
  15. 4g网络什么时候淘汰_4g网络手机。什么时候淘汰
  16. CVPR2020(Enhancement):论文解读《Zero-Reference Deep Curve Estimation for Low-Light Image Enhancement》
  17. C语言----白细胞计数
  18. OpenGL(12)GL库API
  19. 关于app运营的这几个考核指标你不能不了解!
  20. 有关stm32单片机外部低速晶振LSE32.768k注意事项;RTC_WaitForSynchro()卡死;

热门文章

  1. android银河城游戏,Endless Memories安卓版
  2. 服务器cpu占用过高一般是什么原因,如何解决服务器cpu使用率过高的問題
  3. 2022年R1快开门式压力容器操作最新解析及R1快开门式压力容器操作新版试题
  4. QT 信号toggled triggered区别
  5. 怎样把pdf转换成jpg文件
  6. Microsoft HTML Help Workshop 使用
  7. YouTube 深度神经网络在推荐系统上的应用
  8. 只需3步让你电脑瞬间变快10倍
  9. 物联网如何测试(一)
  10. 据说百度的月饼最差劲!!