记录一下。希望对同样有该问题的有用。查了挺多文档,参考了大佬。
本文旨在通过Qt调用Matlab生成的动态共享库(DLL),若是别的调用请查看其余大佬文章。
一、MATLAB 生成 DLL文件
1.1 编译环境配置
ps:(问题注意点写前面) QT调用matlab需要编译器位数一致!!!!!!!不然会出现函数未定义等错误。
Qt 在 Windows 平台的编译环境一般有两种,分别为 MinGW 和 MSVC,为使 DLL 文件的编译平台与 Qt 保持一直,在配置时需要选择相同的编译器,且位数必须一致,比如我使用的环境均为MSVC2017 64bit。MSVC 可以通过安装 Visual Studio 进行配置,网上相关资料很多,这里就不说了。MinGW 没用过,但可以在 MATLAB 附加功能中安装,打开附加功能管理器后,直接搜索Mingw
即可。
在 MATLAB 命令行窗口,使用mbuild –setup
命令查看 MATLAB 中可以配置的编译环境。
如果没有可选编译器,需要自行配置后进行下一步操作。
输入命令后,会显示当前可配置的编译器,如下图所示。
这里我选择C++语言,完成配置。
(需要注意的是,matlab每次重启后,都要重新按以上步骤进行mbuild -setup)
1.2 打包生成 DLL 文件
先使用 MATLAB 编写一个两个数相加的函数,文件名为 add_matlab.m,具体代码如下:
function c = add_matlab(a,b)
c = a + b;
end
在 MATLAB 命令行窗口输入 deploytool
命令,弹出如下对话框。(也可以在上方app里直接找Library Compiler
编译器)
选择 Library Compiler
编译器,如下图所示。
TYPE
选择C++ Shared Library
,EXPORTED FUNCTIONS
选择要编译的文件,这里选择前面编写好的add_matlab.m
文件,如下所示。
选择完成后,点击 Package
按钮,选择编译后的文件放置位置,开始编译打包,稍等片刻即可完成,输出目录中有如下三个文件夹。
for_testing
目录下的文件,用于测试。
for_redistribution
目录中程序MyAppInstaller_web.exe
用于安装 MATLAB 运行时库和本项目生成的 DLL 、LIB 和 H 文件,将程序部署至没有 MATLAB 环境中电脑时,可以使用此方法。
for_redistribution_files_only
目录中的 DLL 、LIB 和 H 文件,就是在 Qt 项目中要使用的文件。H 和 LIB 文件用于 Qt 程序调用,DLL 文件用于保障程序运行。有文章说 v2 目录中的 .ctf 文件在较低版本的 MATLAB 中影响 DLL 接口中的初始化函数,较高版本的MATLAB不需要。在无法初始化时,可以将该文件与 DLL 文件一同放入 debug 文件夹下尝试解决。
二、Qt 调用 DLL
2.1 创建好Qt项目,添加外部库(DLL)
创建一个 Qt 项目,在项目文件目录下新建一个名为matlab_libs
(文件夹名可以自定义随便取),将 MATLAB 编译生成的for_redistribution_files_only
目录下的文件全部拷贝至该文件夹下。
右键点击 Qt 项目目录名,选择添加库
、外部库。
库文件选择Matlab_libs
中的add_matlab.lib
,点击下一步完成 Qt 外部库的添加。
完成后会在项目 .pro 文件中添加如下信息:
win32: LIBS += -L$$PWD/matlab_libs/ -ladd_matlab
INCLUDEPATH += $$PWD/matlab_libs
DEPENDPATH += $$PWD/matlab_libs
2.2 添加 MATLAB 其他依赖库和头文件路径
Qt 项目编译时,不仅需要自己添加的 MATLAB 编译后的库文件,还需要其他 MATLAB 依赖库文件,在工程 .pro 文件中添加如下内容:
# MATLAB 用到的.lib库文件及其搜索路径
LIBS += -LD:/MATLAB/MATLAB_Runtime/v95/extern/lib/win64/microsoft/ -llibmx
LIBS += -LD:/MATLAB/MATLAB_Runtime/v95/extern/lib/win64/microsoft/ -llibmat
LIBS += -LD:/MATLAB/MATLAB_Runtime/v95/extern/lib/win64/microsoft/ -llibeng
LIBS += -LD:/MATLAB/MATLAB_Runtime/v95/extern/lib/win64/microsoft/ -lmclmcr
LIBS += -LD:/MATLAB/MATLAB_Runtime/v95/extern/lib/win64/microsoft/ -lmclmcrrt
LIBS += -LD:/MATLAB/MATLAB_Runtime/v95/extern/lib/win64/microsoft/ -llibmex
# .h文件搜索路径
INCLUDEPATH += D:/MATLAB/MATLAB_Runtime/v95/extern/include
INCLUDEPATH += D:/MATLAB/MATLAB_Runtime/v95/extern/include/win64
(根据自己MATLAB安装位置来修改)
上述路径根据自己安装位置进行替换,需要注意的是,文件路径中不得有空格,若有空格可以使用 quote(),如下:
INCLUDEPATH += $$quote(D:/MATLAB/MATLAB_Runtime/v95/extern/include)
2.3 环境配置
如果要发布程序或者运行在没有 MATLAB 环境的电脑需要安装 MATLAB 运行库,可以通过for_redistribution
目录中MyAppInstaller_web.exe
程序进行安装,也可以直接下载运行库安装程序,下载的运行库必须和生成 DLL 文件的 MATLAB 软件是同一个版本,MATLAB 运行库链接:https://ww2.mathworks.cn/products/compiler/matlab-runtime.html,
运行库的安装根据提示一直点击确定即可。
2.4 调用add_matlab DLL库函数
(1)初始化库函数
在调用 add_matlab() 函数前,必须先使用 add_matlabInitialize() 函数初始化库函数。
(初始化函数在add_matlab.h头文件有,根据不同库,可能有点区别)
(2)MATLAB 编译生成的 DLL 函数接口,保存在add_matlab.h
文件中,add_matlab() 函数如下:
extern LIB_add_matlab_CPP_API void MW_CALL_CONV add_matlab(int nargout, mwArray& c, const mwArray& a, const mwArray& b);
nargout 为函数输出参数的个数,表示其后面紧跟着 nargout 个输出参数。
其他参数为 MATLAB 程序中自定义的输入输出参数,数据类型均为mwArray
类。
(3)mwArray
类
mwArray
类是用于将输入/输出参数传递给 MATLAB Compiler SDK 生成的 C++ 函数的类。
具体使用可参考:mwArray类说明-CSDN博客
2.5 编译运行
简单示例代码具体如下:
#include "matlabtest.h"
#include "ui_matlabtest.h"
#include "matlab_libs/add_matlab.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
if (!add_matlabInitialize())
{
qDebug("add_matlab unsuccessfully initialized");
return;
}
ccc();
}
Widget::~Widget()
{
delete ui;
}
void Widget::ccc()
{
double a = 6.3;
double b = 9.2;
mwArray mwA(1,1,mxDOUBLE_CLASS);
mwArray mwB(1,1,mxDOUBLE_CLASS);
mwArray mwC(1,1,mxDOUBLE_CLASS);
//设置数据
mwA.SetData(&a,1);
mwB.SetData(&b,1);
qDebug()<<mwA.Real().ToString();
qDebug()<<mwB.Real().ToString();
//计算
add_matlab(1,mwC,mwA,mwB);
qDebug()<<mwC.Real().ToString();
}
三:问题
可参考: