栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

node-ffi调用C++编译的动态链接库踩坑记录

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

node-ffi调用C++编译的动态链接库踩坑记录

node-ffi调用C++编译的动态链接库踩坑记录
  • 前言
  • 一、安装相关依赖
  • 二、使用步骤
    • 1.准备好动态链接库
      • 然后编译成dll文件
    • 1.引入库
    • dll查看器的使用
    • __declspec(dllexport)关键字
  • 总结


前言

提示:以下是本篇文章正文内容,下面案例可供参考

一、安装相关依赖

旧版node-ffi不支持高版本的node环境,其他博主也有详细介绍,我就不再赘述了,现在使用V12以上的node版本需要用到ffi-napi以及相关的库,由于该库需要使用到node-gyp进行编译所以需要提前安装好相关环境,node-gyp的安装可以参考这几篇文章nodeffi入门到放弃, electron使用nodeffi

安装好node-gyp的环境以后现在安装ffi-napi相关的库,官方仓库github

npm install ffi-napi
npm install ref-napi
npm install ref-napi
npm install ref-array-napi
二、使用步骤 1.准备好动态链接库

使用Viasual Studio 2017新建一个dll的项目


创建好项目以后就会得到一个默认的这样的文件

然后分别在头文件pch.h和源文件pch.cpp里面添加测试代码

// pch.cpp
int funAdd(int a, int b)
{
	return (a + b);
}

// pch.h
extern "C"
{
	__declspec(dllexport) int funAdd(int a, int b);
}

别忘记按住Ctrl + s保存代码

然后编译成dll文件

注意:编译的时候默认编译成64位的就行了


1.引入库

在项目中新建一个index.js文件和一个dll文件夹(存放刚刚编译的dll文件)

index.js代码如下(示例):

const ffi = require('ffi-napi');
const ref = require('ref-napi');
const ArrayType = require('ref-array-napi');
const path = require('path');

function testDll(){
  const dll = './dll/DLL4.dll';
  const filePath = path.resolve(dll);
  const lib = new ffi.Library(filePath, {
    'funAdd': // 声明这个dll中的一个函数
    [
      'int', ['int', 'int'], // 用json的格式罗列其返回类型和参数类型
    ],
  });
  const result = lib.funAdd(1, 2);
  console.log(result);
}

然后在控制台执行

node index.js


如果没有报错那就恭喜你以及可以成功调用dll文件了

如果遇到了类似这样的报错,Dynamic Linking Error: Win32 error 193,那就是你的动态链接库可能是32位的而你的操作系统是64位的。如果想测试复现这个错误,可以在上面的介绍中将编译的配置项改为x86然后重新编译就可以得到一个32位的dll文件。

请查看相关博客描述常见的错误信息,在这里我也不做赘述了,Electron——常见动态链错误
node-ffi调用dll踩坑记录

dll查看器的使用

在调试过程中如果遇到了Dynamic Linking Error: Win32 error 127的报错,我遇到了三种情况

  1. 你在new ffi.Library的参数里面写的函数名与C++代码的函数名不一致,比如C++里面是funAdd函数你写成funadd
  2. 也可能是函数的参数类型错误,比如funAdd函数的参数类型是int你写成double
  3. 还有一种就是动态链接库里面还引用了别的动态链接库,但是你本地的电脑环境里面没有这个文件引用的别的dll文件

第三种情况就可以使用dll查看器检查你的dll文件是否有问题,参考Win10 查看 DLL 中的函数

我会将这个dll查看器上传到我的资源我的资源中,方便大家下载,免费的哦

把工具下载好了以后,解压文件,找到DependenciesGui.exe这个文件双击运行


可以正常执行的dll文件应该是一下图片中的内容
左侧是你的dll文件依赖的一些其他dll文件的文件树,右侧就是dll文件里面函数名,地址等信息

那我们现在打开一个有问题的dll文件,(这个dll文件是通过Cmake的方式编译的,这个dll文件还依赖了mingw的dll文件)

找到报错的dll文件

然后我找了报错的dll文件



所以报错的原因已经找到了,就是nodejs在调用A这个dll文件的时候,A还依赖了其他的dll文件,但是你的系统里面找不到A依赖的文件所以导致报错,至于报错信息为什么是Dynamic Linking Error: Win32 error 127还有待研究,估计得看源码。

由于该动态链接库是Cmake编译的,而且在编译的时候选择了动态库的形式,所以把这个编译出来的dll库放到其他环境可能就无法运行。最好的解决办法就是编译成静态库,简单的说就是把你编译的目标dll文件所依赖的dll文件一起打包,就像克隆别人的代码仓库,把别人的代码仓库里面的node_modules包一起克隆。如何编译静态库 请参考Clion创建和调用静态库

__declspec(dllexport)关键字

还有一个关键的地方就是在.h的头文件中函数声明前面添加 __declspec(dllexport)关键字,其实不添加这个关键字编译出来的dll文件也可以正常运行,只不过在dll查看器里面看不到你声明的函数,因为头文件不参与编译。

下面放两张参考图


总结

总之踩了各种各样的坑终于把Cmake编译的dll文件跑起来了,踩坑的原因也是因为自己对C++不熟悉,对Cmake不熟悉,对编译原理不熟悉,填坑的时候耗费了大量的时间去查资料。希望对大家有帮助。最好来个一键三联鼓励一下,以后我会多多分享开发中常见的填坑技巧。谢谢大家✨

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/879053.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号