Qt 5.9 与 Matlab 2017b 混合编程基本流程

4 篇文章 2 订阅

内容简介

最近在用Qt编写一个数据处理软件,涉及到很多信号处理的算法,这些都是很成熟的算法,本着找轮子的思路找可用的源程序。GitHub上相关的源代码倒是很多,但是要么缺少实例和文档、要么在Windows下编译出现问题,即便是较大的完整的源程序库,学习其使用也是个比较耗时间的事情。找来找去,最后还是决定用Matlab与Qt混合编程。

本文就介绍使用Qt 5.9和Matlab 2017b进行混合编程的基本流程,主要包括:

  • 如何在Matlab中将m文件编译为C++语言的DLL文件
  • 如何在Qt项目中加入自定义DLL相关的LIB文件,以及MATLAB相关的LIB文件和H文件搜索路径
  • MATLAB运行时DLL文件所在路径,及系统相关的环境变量设置
  • 如何在Qt中调用自定义DLL中的函数,如何通过mwArray类传递输入输出参数

1. Matlab中m文件编译为C++语言的DLL文件

在MATLAB中编写一个简单的两个矩阵相加的函数matAdd.m,其代码如下:

 

function  [C]= matAdd(A,B)
% C= matAdd(A,B)
%  两个矩阵相加
C=A+B;
end

在编译m文件之前,需要保证MATLABCompiler已经设置好了编译器,在MATLAB命令行窗口中使用mbuild –setup 设置使用C编译器。

>> mbuild -setup
MBUILD 配置为使用 'Microsoft Visual C++ 2015 (C)' 以进行 C 语言编译。
	
要选择不同的语言,请从以下选项中选择一种命令:
 mex -setup C++ -client MBUILD 
 mex -setup FORTRAN -client MBUILD

要使用C++编译器,就用命令 mbuild –setup C++ 设置

>> mbuild -setup C++
MBUILD 配置为使用 'Microsoft Visual C++ 2015' 以进行 C++ 语言编译。

我的电脑上安装了Visual Studio 2015,MATLAB会自己查找可用的编译器,若没有自动找到编译器,可能版本兼容问题或其他问题,可搜索相关资料解决问题。

在命令行中输入 deploytool,出现如下的对话框

 

“ApplicationCompiler”用于将m文件编译为exe文件直接运行,“Library Compiler”用于将m文件编译为DLL、COM组件等形式。我们要生成DLL文件,所以选择“Library Compiler”。

 

在上图的MATLAB Compiler窗口中,“TYPE”部分选择C++ shared Library,“EXPORTED FUNCTIONS”是需要导出的m文件,点击右侧的“Add”按钮选择编写的文件matAdd.m。右侧是MATLAB运行时库的安装打包方式,在本机上测试可选择“Runtime downloaded from web”。

保存项目为matAdd.prj,然后点击“Package”按钮进行编译和打包。

打包完成后,在项目文件matAdd.prj的目录下生成与项目同名的子目录,即\matAdd,该目录下有3个文件夹。

matAdd\for_redistribution目录下是文件MyAppInstaller_web.exe,这个是MATLAB运行时库的和本项目的安装文件,运行后可从网上下载MATLAB的运行时库进行安装,还会安装本项目生成的DLL、LIB和h文件。

matAdd\for_redistribution_files_only目录下是编译生成的.dll 、.lib和.h文件,其中.lib和.h文件是在Qt项目编译时需要用到的,.dll文件是程序运行时需要用到的。

 

matAdd\for_testing  目录下是用于测试的,但是dll不是可执行文件,不能直接进行进行测试。

 

2.  Qt 5.9项目中使用matAdd.dll

2.1 Qt项目创建与UI设计

创建一个QtWidget Application项目testAdd,主窗口基于QWidget。程序运行时如下图。

2.2  库文件matAdd.lib 的加入

在项目目录下新建一个include目录,将前面编译生成的matAdd\for_redistribution_files_only目录下的matAdd.lib和matAdd.h文件复制到此目录下。

在Qt Creator里,testAdd项目节点上单击右键,选择“Add Library...”,在出现的向导中首先选择“External Library”,后续出现下图的界面,选择库testAdd\include\目录下的库文件matLib,其他选择如图。

在此对话框完成后,在testAdd.pro文件中会增加如下的几行:

 

win32: LIBS += -L$$PWD/include/ -lmatAdd
	
INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD/include

为了方便查看matAdd.h的内容,还可以将matAdd.h文件添加到项目中,但是要注意不要修改matAdd.h文件的内容。

2.3  Matlab其他依赖库和头文件搜索路径的加入

除了自己编译生成的DLL相关的.lib文件和头文件,要编译此Qt项目,还需要用到MATLAB的几个.lib文件和.h文件。

我的电脑上,MATLAB2017b安装在D:\ MATLAB2017b目录下,在testAdd.pro文件中需要加入如下的设置:

 

# .h文件搜索路径
INCLUDEPATH += D:/MATLAB2017b/extern/include
INCLUDEPATH += D:/MATLAB2017b/extern/include/Win64
	
# 用到的MATLAB 的.lib库文件 及其搜索路径
INCLUDEPATH += D:/MATLAB2017b/extern/lib/win64/microsoft
DEPENDPATH += D:/MATLAB2017b/extern/lib/win64/microsoft
	
win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -llibmex
win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -llibmx
win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -llibmat
win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -llibeng
win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -lmclmcr
win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -lmclmcrrt

注意,若路径名称中含有空格,需要使用quote(),如

     #INCLUDEPATH+=$$quote(D:/MATLAB2017b/extern/include)

2.4 系统环境变量的设置

额外加入的一些库实际上对应于MATLAB运行时的一些DLL文件,这些运行时文件主要在以下几个目录下,所以要保证这些目录添加到了Windows的环境变量PATH里。

D:\MATLAB2017b\runtime\win64;
D:\MATLAB2017b\bin\win64;

若是程序发布到没有安装MATLAB的电脑上,需要用Matlab Compiler编译生成的安装包,本例就是 matAdd\for_redistribution目录下的MyAppInstaller_web.exe。

若只是要独立安装MATLAB运行时库,在MATLAB 命令行里输入 mcrinstaller可以得到离线的MATLAB运行时库安装文件的路径。

>> mcrinstaller
ans ='D:\MATLAB2017b\toolbox\compiler\deploy\win64\MCRInstaller.exe'

2.5  编写使用DLL内函数matAdd()的代码

在Qt Creator里,为widget.ui上的按钮编写如下的代码。

 

void Widget::on_btnAdd_clicked()
{
   if (!matAddInitialize()) //DLL 初始化
   {
      ui->lineEdit_C->setText("DLL initialization failed");
      return;
   }

   double   vectA[]={1,2,3}; //向量A
   double   vectB[]={5,6,7};  //向量B

   int   rowCnt=1;   //行数
   int   colCnt=3;   //列数
   int   elementCnt=3; //元素个数

   mwArray matrixA(rowCnt,colCnt,mxDOUBLE_CLASS, mxREAL);//定义数组
   matrixA.SetData(vectA,elementCnt); //将C++ 的一维数组存储到 MATLAB的二维数组

   mwArray matrixB(rowCnt,colCnt,mxDOUBLE_CLASS, mxREAL);//定义数组
   matrixB.SetData(vectB,elementCnt); //

//计算
   mwArray matrixC(rowCnt,colCnt,mxDOUBLE_CLASS, mxREAL);//定义数组,double类型
   int nargout=1;//输出变量个数
   matAdd(nargout,matrixC,matrixA,matrixB);//C=A+B

//读取结果
   int dim=2; //按照二维数组读出matrixC
   double   av=matrixC.Get(dim,1,1); //第1行,第1列
   double   bv=matrixC.Get(dim,1,2);// 第1行,第2列
   double   cv=matrixC.Get(dim,1,3); // 第1行,第3列

//   int dim=1; //按照向量读出matrixC
//   double   av=matrixC.Get(dim,1); //第1个元素
//   double   bv=matrixC.Get(dim,2); //第2个元素
//   double   cv=matrixC.Get(dim,3); //第3个元素

   QString  str=QString::asprintf("%.0f, %.0f, %.0f", av,bv,cv); 
   ui->lineEdit_C->setText(str);
}

(1)DLL的初始化

在使用matAdd.dll里的函数之前,必须先初始化。matAddInitialize()是matAdd.h文件里面的库初始化函数。

(2)matAdd函数的输入输出参数

mwArray是MATLAB的数组类,MATLAB编译生成的DLL的接口函数的参数都是采用mwArray类型,例如matAdd.h文件中的函数matAdd()的函数原型为:

extern LIB_matAdd_CPP_API void MW_CALL_CONV matAdd(int nargout, mwArray& C, const mwArray& A, const mwArray& B);

不去管那一堆的前缀,函数的4个参数:

  •  int  nargout 是输出参数个数,表示后面紧跟着的nargout个变量是输入参数,由matAdd.m文件可知,matAdd()有1个输出参数C
  •   mwArray  &C 输出参数,对应于matAdd.m文件里的输出参数C

  •   mwArray  &A,  const mwArray  &B  两个输入参数,对应于matAdd.m文件里的两个输入参数A 和B

由m文件的函数编译生成的C++函数都是这样的参数定义顺序,格式比较统一。

(3)mwArray类的使用

Qt 程序要调用matAdd.dll里的函数matAdd(),就需要按照函数原型传递输入和输出参数,主要是mwArray类的使用。例输入参数数组matrixA的定义和传递数据的代码是:

 

   mwArray matrixA(rowCnt,colCnt,mxDOUBLE_CLASS, mxREAL); 
   matrixA.SetData(vectA,elementCnt); 

定义mwArray类型的变量matrixA时,利用构造函数传递了数组的行数、列数、元素类型、实数或复数类型

语句matrixA.SetData(vectA,elementCnt)将 一维向量vectA的数据内容赋值给matrixA,元素个数为elementCnt,等于行数*列数。即使matrixA是一个二维数组,使用SetData赋值时,输入vectA也必须是一个向量,是逐列存储的。

同样赋值matrixB,定义返回矩阵matrixC。

调用matAdd()函数进行计算的代码是:

 

  int nargout=1;//输出变量个数
  matAdd(nargout,matrixC,matrixA,matrixB);//C=A+B

得到matrixC之后,需要读取出matrixC的数据内容进行显示。

读取mwArray的某个元素的值用mwArray::Get()函数。函数的第一个变量表示数组维数,维数为1表示数组是向量,获取元素只需一个索引即可,matrixC是一维向量,可以用下面的代码读取数据:

   int dim=1; //按照向量读出matrixC
   double   av=matrixC.Get(dim,1); //第1个元素
   double   bv=matrixC.Get(dim,2); //第2个元素
   double   cv=matrixC.Get(dim,3); //第3个元素

维数为2表示数组是二维数组,获取一个元素需要行号和列号。matrixC是向量,也可以看做只有1行的二维数组,所以下面的代码也是可行的

   int dim=2; //按照二维数组读出matrixC
   double   av=matrixC.Get(dim,1,1); //第1行,第1列
   double   bv=matrixC.Get(dim,1,2);// 第1行,第2列
   double   cv=matrixC.Get(dim,1,3); // 第1行,第3列

注意:mwArray数组的下标都是从1开始的,与C/C++的数组元素下标从0开始不同。

2.6  编译和运行

代码无语法错误后编译并运行,但是运行时闪退。这是Matlab2017b的一个少见的错误,在本人另一篇博文《Matlab 2017b编译成exe或DLL文件后无法运行的问题及其解决方法》里有描述和解决办法。

注意:在Qt Creator里编译时,应选择MSVC2015 64bit编译器,因为在Matlab里是用MSVC 201564位编译生成的DLL文件,若在Qt里使用其他的32位编译器将无法正常运行。

编译后,还需要将3个DLL文件复制到编译后的\release目录下,才可以正常运行。其中,matAdd.dll就是我们在MATLAB里编译生成的DLL。另外的SSLEAY32.DLL和LIBEAY32.DLL是从Matlab的安装目录 \bin\win64下复制过来的。

一切正常后,运行时点击“matAdd()计算”按钮,就可以得到计算结果。

 

本文Qt 5.9 测试项目完整源码下载地址

    http://download.csdn.net/download/hongandyi/10268476

或    https://pan.baidu.com/s/1FJHMZdSl_zMH3JRFQlJRgg    提取码:ptnd

 

参考:

Matlab 2017b编译成exe或DLL文件后无法运行的问题及其解决方法

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 39
    点赞
  • 205
    收藏
    觉得还不错? 一键收藏
  • 51
    评论
MATLAB 2017bMathWorks公司开发的一款强大的科学计算软件。它不仅具备计算、算法开发和数据可视化等基本功能,还提供了丰富的工具箱,如信号处理、图像处理、控制系统、优化等等,可满足不同领域的科研和工程应用需求。 诚通网盘是一家网络存储服务提供商,提供了网盘存储和文件分享等功能。将MATLAB 2017b与诚通网盘结合使用,可以带来一些方便和好处。 首先,MATLAB 2017b的数据处理和分析功能强大且灵活,可以处理大量数据和进行复杂的计算,但它可能需要大量的磁盘空间。将MATLAB 2017b与诚通网盘结合,可以将数据和计算结果存储在网盘中,充分利用网盘提供的大容量存储空间,避免本地磁盘空间不足的问题。 其次,诚通网盘提供了文件分享和协作的功能,能够方便地与他人共享MATLAB代码、数据和结果。MATLAB 2017b具备强大的编程能力,可以编写复杂的算法和模型,多人协作不可或缺。通过将MATLAB文件上传到诚通网盘,可以快速分享给其他同事或合作者,实现共同编辑和讨论,提高工作效率和减少沟通成本。 最后,诚通网盘还支持安全的云存储,可以对上传的MATLAB文件进行备份和恢复。在使用MATLAB 2017b进行科研或工程项目时,数据和计算结果的安全是非常重要的。通过将MATLAB文件存储在诚通网盘中,可以避免本地硬盘故障或数据丢失的风险,保护重要的科研成果和项目资料。 综上所述,将MATLAB 2017b与诚通网盘结合使用,可以发挥出它们各自的优势,提高工作效率、方便文件协作、保护数据安全,为科研和工程项目的顺利进行提供强有力的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 51
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值