Qt调用Matlab生成dll的配置过程与问题排查解决记录
前置
- 编译器 msvc_2019_x64
- Qt 5.15.2
- Matlab R2022b
1. Matlab生成dll
确保你的.m文件是一个funciton,并且有返回值,长得像这样
然后在Matlab控制台输入命令:
1 | mex -setup |
如图:
选择你的编译器,我这里选择的是Microsoft Visual C++ 2019 (C),总之前后要对应起来。
接下来选择:
1 | mex -setup C++ |
看到输入如下字样后:
1 | MEX 配置为使用 'Microsoft Visual C++ 2019' 以进行 C++ 语言编译。 |
接着输入:
1 | mcc -W cpplib:detect -T link:lib detect.m -C |
- -W 控制编译之后的封装格式
- cpplib 指编译成C++的lib文件;若要编译成C的lib文件,就用需要将cpplib改为lib
- detect 指生成文件的文件名
- -T 表示目标
- link:lib 表示要连接到一个库文件的目标,目标的名字即是.m函数的名字
完成之后会在Matlab源码的当前路径生成如下格式的文件:
需要用到的有
- detect.dll
- detect.h
- detect.lib
- detect.ctf(在v2文件夹里)
2. Qt配置库链接
在项目中需要调用 MATLAB 生成的 detect.dll
,使用 Qt (MSVC 编译器) 进行集成。在 .pro
文件中配置了 Matlab Runtime 和自定义库的链接。
- 将detect.lib拷贝到项目根路径libs文件夹中
- detect.dll和detect.ctf放到exe同级路径
- detect.h放到你常规的header路径,然后增加到项目中,引用进来
pro文件关于lib以及matlab的配置如下1
2
3
4
5
6
7
8
9
10
11
12# matlab
INCLUDEPATH += "D:/Program Files/MATLAB/MATLAB Runtime/R2022b/extern/include"
LIBS += -L$$PWD/libs \
-ldetect
INCLUDEPATH += "D:/Program Files/MATLAB/R2022b/extern/include"
INCLUDEPATH += "D:/Program Files/MATLAB/R2022b/extern/include/cpp"
LIBS += -L"D:/Program Files/MATLAB/R2022b/extern/lib/win64/microsoft"
LIBS += -L"D:/Program Files/MATLAB/R2022b/extern/bin/win64"
LIBS += -lmclmcrrt3. 环境变量
添加系统变量PATH1
2D:\Program Files\MATLAB\R2022b\bin\win64
D:\Program Files\MATLAB\R2022b\runtime\win64
4. 代码调用测试
1 | // 自定义错误输出函数 |
注意不要调用:
1 | if (!mclInitializeApplication(NULL, 0)) { |
完成detect_Initialize()方法的调用之后控制台会打印:
我也不知道为什么会输出两次,而且很慢(卡住主线程,可以考虑放在单独线程)
之后可进行业务方法调用了:
1 | void invokeMatlab2(QVector<QVector<double>> data) { |
输出结果:
最后记得在析构函数里调用释放方法:
1 | detect_Terminate(); |
5. 遇到的问题与报错
- 无法打开文件 “mclcpp.lib”
1
error: LNK1104: 无法打开文件“mclcpp.lib”
- 无法打开文件 “Files\MATLAB\R2022b\extern\lib\win64\microsoft.obj”
1
error: LNK1104: 无法打开文件“Files\MATLAB\R2022b\extern\lib\win64\microsoft.obj”
- DLL无效或损坏
1
error: LNK1107: 文件无效或损坏: 无法在 0x300 处读取
- 函数重复定义
1
error: LNK2005: "void __cdecl detect(int,class mwArray &,class mwArray const &)" 已经在 detect.obj 中定义
解决步骤
1. 检查 MATLAB 运行时库链接
- 正确设置 MATLAB Runtime 路径:
1
2
3
4
5
6INCLUDEPATH += "D:/Program Files/MATLAB/R2022b/extern/include"
INCLUDEPATH += "D:/Program Files/MATLAB/R2022b/extern/include/cpp"
LIBS += -L"D:/Program Files/MATLAB/R2022b/extern/lib/win64/microsoft"
LIBS += -L"D:/Program Files/MATLAB/R2022b/extern/bin/win64"
LIBS += -lmclmcrrt - 注意 不要 错误地链接成
.obj
文件路径,LIBS
后面只能跟 库文件 (.lib) 路径!
2. 处理 mclcpp.lib 缺失问题
- 发现
mclcpp.lib
原本想手动链接,但其实实际只需要mclmcrrt.lib
,不需要单独引入mclcpp.lib
。 - 因此注释掉了:
1
# LIBS += -lmclcpp
3. 解决 DLL 无效或损坏报错
出错原因:直接将 DLL 文件用作了
.lib
文件链接。正确做法:应使用 MATLAB Compiler SDK 工具链生成对应的
.lib
文件,并链接.lib
,运行时动态加载.dll
。修改链接方式为:
1
LIBS += -L$$PWD/dll -ldetect
确保编译时用的是
.lib
,不是.dll
。
4. 避免函数重复定义
- 发现源码中存在
detect.cpp
文件,同时又链接了detect.lib
。 - 这样导致同一函数既在静态库又在源文件中定义,引起 LNK2005 冲突。
- 解决办法:
- 删除 项目中的
detect.cpp
和detect.h
。 - 保持仅通过
detect.lib
调用外部函数接口。
- 删除 项目中的
最终 .pro
文件关键配置(MATLAB部分)
1 | # Matlab 头文件路径 |
小结
.lib
是编译时用的,.dll
是运行时用的,两者不可混淆。- 链接路径中有空格的地方一定要加上引号
"..."
。 - 遇到 LNK2005,注意不要重复定义同名函数。
INCLUDEPATH
和LIBS
的顺序也可能影响编译。