当前位置: 首页 > news >正文

mingw下使用msvc的onnxruntime库

mingw下使用msvc的onnxruntime库

  • 背景
  • 方法1:直接下载release版——失败
  • 方法2:使用mingw编译onnx——失败
  • 方法3:mingw下调用msvc库
    • 3.1 直接调用已有onnxruntime.dll——失败
    • 3.2 动态加载onnxruntime.dll——失败
    • 3.3 静态库——失败
  • 方法4:VS编译一个不依赖msvc库的onnxruntime.dll——成功
    • 安装Visual Studio2022
    • 启动VS命令行端
    • 启动编译

背景

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

方法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直接编译链接/调用,不会报错了。

相关文章:

  • 某数官网 点选验证
  • 《C 语言字符串操作从入门到实战(下篇):strncpy/strncat/strstr 等函数原理与实现》
  • (初级)前端初学者入门指南:HTML5与CSS3核心知识详解
  • 安卓手机安装 ChatGPT 全流程图文指南
  • KaihongOS设备开发中Sensor 驱动开发
  • 【ffmpeg】硬软编码
  • 深入理解Diffusers: 从基础到Stable Diffusion
  • Tomcat多实例配置
  • AttributeError: module ‘cv2.dnn‘ has no attribute ‘DictValue‘错误解决方法
  • PCB设计教程【入门篇】——电路分析基础-电路定理
  • Android logcat命令汇总
  • Dockers Compose常用指令介绍
  • 深入探究C++11的核心特性
  • Armadillo C++ 线性代数库介绍与使用
  • 深入探讨Java循环:类型、性能与优化
  • 【Java高阶面经:数据库篇】19、分库分表查询困境:无分库分表键时的高效应对
  • 鸿蒙运动开发:计算户外运动步频与步幅,与地图路线绘制
  • 在 “Linux 9“ 系统快速安装配置RabbitMQ
  • 英伟达有意入股 PsiQuantum,释放战略转向量子计算的重要信号
  • Java 海康录像机通过sdk下载的视频无法在线预览问题
  • 华夏网站建设/app联盟推广平台
  • 自己做的网站网站搜索/百度词条搜索排行
  • 微信公众平台人工电话/网站播放视频速度优化
  • 燕郊个人网站建设/重庆网站seo搜索引擎优化
  • 亚马逊品牌网站建设/推荐几个靠谱的网站
  • 宿迁企业做网站/网站建设选亿企网络