Qt与MATLAB混合编程
前言:本文主要讲述以Qt来开发,MATLAB做数学计算,c++来编写程序,将计算的结果生成相应的库文件或者直接生成一个可执行文件给Qt调用,以此来实现Qt与MATLAB混合编程。
环境概述:
操作系统:Win10 64位
Qt版本:Qt5.12.0
Matlab版本:Matlab2016a
1.设置MATLAB的编译器
mbuild -setup // 1打开MATLAB,输入此命令
Welcome to mbuild -setup. This utility will help you set up
a default compiler. For a list of supported compilers, see
http://www.mathworks.com/support/compilers/R2012b/win32.html
Please choose your compiler for building shared libraries or COM components:
Would you like mbuild to locate installed compilers [y]/n? y // 2输入y,允许mbuild定位编译器
Select a compiler:
[1] Lcc-win32 C 2.4.1 in D:\DEVELO~1\MATLAB\R2012b\sys\lcc
[2] Microsoft Visual C++ 2010 in D:\DevelopProgramFiles\VS2010
[0] None
Compiler: 1 // 3选择编译器,输入1即选用了[1] Lcc编译器,如果安装了VS2010可以选择2
Please verify your choices:
Compiler: Lcc-win32 C 2.4.1
Location: D:\DEVELO~1\MATLAB\R2012b\sys\lcc
Are these correct [y]/n? y // 4确认路径正确,输入y
Warning: Support for LCC with MATLAB Compiler and builder products
will be discontinued in a future release.
For a list of currently supported compilers see:
http://www.mathworks.com/support/compilers/R2012b/win32.html
Trying to update options file: C:\Users\shansanmeng\AppData\Roaming\MathWorks\MATLAB\R2012b\compopts.bat
From template: D:\DEVELO~1\MATLAB\R2012b\bin\win32\mbuildopts\lcccompp.bat
Done . . .
2.打开MATLAB,选择New->Function,写一个测试文件test.m,内容如下
function y = test( )
% a test for qt and matlab mixed program
% Detailed explanation goes here
x = 0:0.01:25;
y = -x.^2 + 4 * x + 450;
plot(x, y, ‘LineWidth’, 2);
end
点击”Run”后,显示结果如下:
3.将MATLAB的当前工作路径切换到test.m所在的文件夹,输入:
mcc -W lib:testdll -T link:lib test.m
4编译成功后会出现以下所示的文件
5.显式链接法,即显式调用testdll.dll(见示例:testProgramWithMatlab)
(1)新建一个Qt测试程序,将testdll.dll拷贝到Qt运行后生成的Debug文件夹下
(2)确定系统的环境变量中有下面变量,路径根据自己的安装目录所定
D:\DevelopProgramFiles\MATLAB\R2012b\runtime\win32
(3)在pro文件中添加以下内容,路径要根据你的安装情况而定
INCLUDEPATH += D:/DevelopProgramFiles/MATLAB/R2012b/extern/include
INCLUDEPATH += D:/DevelopProgramFiles/MATLAB/R2012b/extern/include/win32
LIBS += -LD:/DevelopProgramFiles/MATLAB/R2012b/extern/lib/win32/microsoft -llibmx
#LIBS += -LD:/DevelopProgramFiles/MATLAB/R2012b/extern/lib/win32/microsoft -lmclmcr
#LIBS += -LD:/DevelopProgramFiles/MATLAB/R2012b/extern/lib/win32/microsoft -lmclmcrrt
(4)在mainwindow.ui上添加两个按钮,分别进入他们的clicked()槽函数
(5)在mainwindow.h中添加一个QLibrary对象m_lib
(6)用Denpendency Walker查看生成的dll文件的export函数,程序里要使用
(7)修改mainwindow.cpp文件如下
#include “mainwindow.h”
#include “ui_mainwindow.h”
#include
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
// 定义函数指针,以备调用
typedef bool MW_CALL_CONV (Fun)(int, mxArray*);
typedef bool MW_CALL_CONV (*Fun2)(void);
typedef void MW_CALL_CONV (*Fun3)(void);
void MainWindow::on_pushButton_clicked()
{
m_lib.setFileName(“testdll.dll”);
if (m_lib.load()) // 加载库
{
Fun open = (Fun)m_lib.resolve("_mlfTest"); // 援引_mlfTest函数
Fun2 init = (Fun2)m_lib.resolve("_testdllInitialize"); // 援引_testdllInitialize
if (open)
{
if ( init() ) // 初始化DLL库
{
open(1, NULL); // 执行功能函数,即m文件里的函数
}
}
}void MainWindow::on_pushButton_2_clicked()
{
Fun3 termi = (Fun3)m_lib.resolve("_testdllTerminate"); // 援引_testdllTerminate
termi(); // 结束DLL库
m_lib.unload();
QMessageBox::information(NULL, “ok”, “Dll is termi”);
}
(8)编辑完成后点击运行会报错,如下,说不认识“maxInt64”和“maxUint64”
(9)双击错误打开报错文件mclmcr.h,可以看到一串宏开关语句,这里面应经定义了这两种数据类型了,他需要根据编译器的类型或者应该说平台进行选择,因为这个不是标准类型的原因吧。
(10)因为我们前面采用的是LCC编译器,所以这里还需要在pro文件里加入一句
DEFINES += LCC
(11)再编译就可以通过了,这时点击“显示”结果如下,可以看到结果和在MATLAB中运行的一样,这样就说明我们调用成功了
说明:上面采用的是LCC编译器,当然也可以用VS2010所带的编译器,你可以在这个网http://www.mathworks.com/support/compilers/R2012b/win32.html 查看你的MATLAB支持的编译器类型。
按照之前的步骤用VS2010编译器去编译test.m,生成的dll文件用Dependency Walker查看如下所示,可以看到函数名不是_xxx类型的,而是和头文件里的一致。
需要说明的是,本应该将pro文件里的DEFINES += LCC 更改为DEFINES += _MSC_VER,但是改完之后会报错。从前面可以知道, __LCC__和_MSC_VER对maxInt64与maxUint64的定义是一样的,所以这里可以继续用DEFINES += LCC。
6.隐式链接法(见示例:testlib)
(1)将第三步编译生成的testdll.h和testdll.lib拷贝到testlib工程文件夹下,将testdll.dll拷贝到Qt编译生成的debug文件夹下(注:其实这些都不是固定的,只要你的工程能够找到他们即可,可按照自己的习惯配置)。
(2)修改pro文件,将testdll.lib加进来,并将testdll.h加入到工程里面
(3)添加相应的头文件,直接使用testdll.h里面的函数就可以了,要注意导出的函数名。
7.采用进程的方式,即将m文件编译成可执行文件在Qt中调用,参见示例文件testexe
将MATLAB的当前工作路径切换到test.m所在的文件夹,输入:
mcc -m test
编译成功后就会生成test.exe文件,这样就可以在Qt中用进程来调用了。
两点说明:
(1)关于使用MATLAB引擎的方式,因为需要安装完整的MATLAB,独立性差,所以这里就不做介绍了,具体的方法可以参见甄梓宁的《C语言环境中调用Matlab程序指南》,推荐看看这篇文章。
(2)上面介绍的三种方式,程序发布时,在目标机器上至少需要安装MCR,可到官网下载。综合来看,采用显式链接的方式较好。
参考文章:
[1]http://blog.sina.com.cn/s/blog_4dc31b560100qqcw.html
[2]C语言环境中调用Matlab程序指南.甄梓宁
[3]http://wenku.baidu.com/link?url=ghNZ0WPZDolFQ5jUvpw5ZC1Oh7fJS3w-JKwmuPT-GjTy4hyi50YCBUwFUEMVZvmNfBBzlQgLQ1KztbdyHAnnm4rSPvuBm21lBI07L6Nb18q
[4]http://zhidao.baidu.com/link?url=zFisP1UOrkr3yi0_Oj5-gx8f8aOh9SculfTufallBFKarBMeE7FQjctDZaRTYMQphf2qlM2eZmG92xQ5pVIvzK