mingw下使用msvc的onnxruntime库

背景

我有个算法A.dll,为了兼容多平台使用了mingw环境编译Windows版本。
A需要用到onnx,所以需要链接onnxruntime.dll。
赶时间直接去到方法4。不赶时间建议全部看完,能了解其中的原理。
文末附上已编译好的dll,免费下载,求点赞

方法1:直接下载release版——失败

你是不是和我一样想到直接下载:https://github.com/microsoft/onnxruntime/releases
恭喜你,第一个坑,release的Windows版本的dll,是用Visual Studio编译,基于msvc运行时库的,而你的A.dll是基于mingw运行时库的。
当你的A.dll加载onnxruntime.dll时,会依赖如msvcp140.dll、vcruntime140.dll这些库,就会崩溃!

方法2:使用mingw编译onnx——失败

经过上面折腾,你就想:那我就自己编译onnx呗,恭喜你,进入第二个坑:onnxruntime在Windows上只支持Visual Studio编译
给你看看github上的留言:
在这里插入图片描述
在这里插入图片描述
人家已经明确不支持了。当然我也没直接放弃,也是挣扎过的,遇到了很多问题,包括:

  1. 报错protoc Error -1073741515
  2. flatbuffers版本不对
  3. 报错: #pragma warning
  4. 报错: sal.h重复定义
    坑太深,就先不折腾了,建议兄弟姐妹们能把它解决,毕竟这才是正道!

我是这样编译的:
打开mingw64命令行,进入目录:onnxruntime-1.22.0/cmake/build_mingw

cmake .. -G "MinGW Makefiles" \
  -DCMAKE_BUILD_TYPE=Release \
  -Donnxruntime_BUILD_SHARED_LIB=ON \
  -Donnxruntime_BUILD_UNIT_TESTS=OFF \
  -Donnxruntime_ENABLE_PYTHON=OFF \
  -DCMAKE_INSTALL_PREFIX=`pwd`/install \
  -Donnxruntime_USE_FULL_PROTOBUF=OFF \
  -Donnxruntime_USE_CUDA=OFF

编译

mingw32-make.exe

方法3:mingw下调用msvc库

既然只有msvc库,那就研究下什么办法可以调用呗
(这里就得吐槽下CSDN下搜到相关的文章,都是要收费的,这么缺钱吗?不懂得分享和互助吗?建议去google搜索,很多资料)

这里总结一下:就是你的msvc下编译的dll,需要封装出C接口,不能提供c++接口,因为msvc和mingw的库函数符号命名有差异,无法调用c++的接口。刚好我们的onnxruntime库已经提供了c接口了onnxruntime_c_api.h
可是这些文章没提到一个根源,请往下看

3.1 直接调用已有onnxruntime.dll——失败

我的A.dll直接连接使用onnxruntime.dll,运行时崩溃,原因上面说过,onnxruntime.dll会依赖msvcp140.dll这些,就会崩溃

3.2 动态加载onnxruntime.dll——失败

就是不在编译阶段link,在代码里面动态load,实际也是会依赖msvcp140.dll,依旧崩溃

3.3 静态库——失败

我就想既然onnxruntime.dll会依赖msvcp140.dll,那我把这个动态库变成静态库不就好咯?搜索了一下找到下面方案

gendef.exe  onnxruntime.dll  #从MSVC的DLL中提取导出符号列表,生成.def 文件
dlltool -d onnxruntime.def -l libonnxruntime.a -D onnxruntime.dll  #通过 dlltool 将 .def 转换为 .a 文件

开始我以为是生成libonnxruntime.a静态库咯,还依赖个毛线其它库呀,谁知道上面操作实际是这样的:

  • 编译阶段
    MinGW 链接 libonnxruntime.a,解析符号引用。
    .a 文件中的符号指向 onnxruntime.dll 的导出函数地址(通过 .def 定义)。

  • 运行阶段
    A.dll 加载时,操作系统自动绑定到 onnxruntime.dll。
    函数调用通过 DLL 的导出表正确跳转。

也就是说,最后还是调用onnxruntime.dll,白搞。

方法4:VS编译一个不依赖msvc库的onnxruntime.dll——成功

经过上面方法3你也应该知道问题的根因了,就是官方release的onnxruntime.dll会依赖msvc运行时库。所以只要我们编译一个不依赖msvc运行时库的onnxruntime.dll就可以了。
也就是:

  1. 使用Visual Studio,按照官方方法编译,静态连接msvc库,编译出onnxruntime.dll
  2. mingw程序正常使用这个onnxruntime.dll

安装Visual Studio2022

安装向导里面,只需要选择 C++的桌面开发,勾选

  1. C++ MSVC 工具链
  2. Windows sdk 11

启动VS命令行端

我的路径是:
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2022\Visual Studio Tools\VC
有4个
x64 Native Tools Command Prompt for VS 2022
x64_x86 Cross Tools Command Prompt for VS 2022
x86 Native Tools Command Prompt for VS 2022
x86_x64 Cross Tools Command Prompt for VS 2022
命名规则:目标平台——宿主平台,所以x86_x64意思是在64位机器上编译32位程序,所以我们应该选择x64 Native Tools

启动编译

根据自己需要调整

python ./tools/ci_build/build.py ^
    --cmake_generator "Visual Studio 17 2022" ^
    --build_dir ./target/ ^
    --config Release ^
    --parallel 8 ^
    --enable_msvc_static_runtime ^
    --skip_tests ^
    --skip_submodule_sync ^
    --build_shared_lib

编译出来的onnxruntime.dll,可以mingw直接编译链接/调用,不会报错了。

现成资源:https://download.csdn.net/download/JCYAO_/90986490 只求点个小心心

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值