Qt(或者VS)+Matlab混合编程

来源:互联网 发布:rtu编程 编辑:程序博客网 时间:2024/05/21 10:21

网上虽然有一些VS+Matlab混合编程的博客,但是有很多行不通的地方,我按照流程依然碰到了很多比较新的问题,现在将问题以及解决方案做出整理,希望可以帮到需要帮助的盆友。

环境:Qt 5.5.1(Qt Creator 3.5.1) + VS2013(64位) + Matlab R2014a

第一步:用Matlab根据(.m)函数文件生成(.dll,.h,.lib,.ctf)文件

(1)新建->函数->保存

function b = myFunc(a)b = a.*a;end


(2)调用编译器,生成(.dll,.h,.lib,.ctf)文件;这一步在编译器上可能会有比较多的问题:

首先,检查一下自己的mcc编译器是否可用

命令行输入指令 !mcc

正常的结果应该如下(指令结果比较长,我只截取了上面一部分):

>> !mccMCC Invoke MATLAB to C/C++ Compiler (Version 5.1).  MCC [-options] fun [fun2 ...]   Prepare fun.m for deployment outside of the MATLAB environment.  Generate wrapper files in C or C++ and optionally build standalone  binary files.   Write any resulting files into the current directory, by default.   For all targets except standalone, if more than one file is  specified, a C or C++ interface is generated for each file.  The only exception to this rule is when the file is specified  with a '-a' flag.   If C or object files are specified, they are passed to MBUILD along  with any generated C files.   If conflicting options are presented to MCC, the rightmost conflicting  option is used.   OPTIONS:   a<filename> Add <filename> to the CTF archive. If the specified file  is an M, mex or p file, this function will not be exported in the  resulting target. 



如果出现error,那么就是Matlab的编译器不能用,原因是Matlab并未完全破解,


也就是说,有证书编号的,而不是unknown,这就需要自己重新激活或者重新找一个靠谱的Matlab安装包了;当然我还发现有一些没有完全破解的,就是有证书编号,但是编译器依然不能用,这个解决方法如下:

适用于已安装compiler但破解不完全的,http://pan.baidu.com/s/1qWFbOjq,提取码84rg ,下载后解压,把install.jar以及相应位数的三个文件(compiler.dll,mcc.exe,libmwservices.dll)复制到对应位置替换即可,另外把license.lic改为与MATLAB\licenses文件夹下的那个lic文件同名,复制并替换之。

解决了编译器问题之后,输入指令:mex -setup


如果安装了VS2013的话应该是有Microsoft Visual C++ 2013这个选项的,我们选择mex -setup C++,然后选择VS2013的C++编译器即可

然后输入指令:mbuild -setup


选择 mex -setup C++ -client MBUILD,然后进一步点击VS2013C++编译器即可

之后就可以调用mcc编译指令来完成我们的第一步了,当然Matlab文件夹要设定为我们.m所在的文件夹,输入指令:

mcc -W cpplib:libmyFunc -T link:lib myFunc.m -C

这个指令有一些需要解释,网上有三个版本,有的前面加了-t,有的后面没有-C,那样都是行不通的,有-t的话指令不支持了,编译出错,之所以后面加上 -C是为了生成.ctf文件,这个文件对后面的库初始化很重要。OK,这一步完成,我们就有了libmyFunc.h,libmyFunc.lib,libmyFunc.dll,libmyFunc.ctf四个文件。

中间插一些小工具:链接: https://pan.baidu.com/s/1dFLAn8t 密码: fifh,这个软件可以查看dll文件里面的函数



我们需要用的函数是libmyFuncInitialize,libmyFuncterminate,以及mlxMyFunc。有的网友会问,为什么没有所谓的mlfmyFunc,C++编译出来的dll文件确实只有mlxmyFunc,要想使用mlfmyFunc,需要使用C编译器,指令如下:mcc -W lib:libmyFunc -T link:lib myFunc.m -C,这样生成的dll文件里面就有mlfmyFunc函数了,当然,功能是一样的。

第二步:QT中调用生成的库,有显示调用和隐式调用两种方式,显式调用一般是在没有.lib文件的情况下使用,隐式调用则显得很方便,清洁明了,所以这里我们只介绍一下隐式调用

(1)首先将上面生成的.h,.lib文件拷到QT的.h文件目录下面,然后把.dll,.ctf文件拷到debug输出目录下面,这方面Qt和VS不一样的是,VS的.exe文件和.h,.cpp等文件是在同一个目录下面的,但是Qt的输出目录是自己设置的,需要先空工程运行一下,就可以找到debug目录了

(2)然后就是在.pro文件里面配置Matlab库和头文件的路径了,如下图所示即可:

QT       += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = MatlabTestTEMPLATE = appSOURCES += main.cpp\        mainwindow.cppHEADERS  += mainwindow.h \            libmyFunc.hFORMS    += mainwindow.uiOTHER_FILES += libmyFunc.ctfINCLUDEPATH += E:\Matlab2014a\Matlab2014aInstall\extern\include\               E:\Matlab2014a\Matlab2014aInstall\extern\include\win64LIBS += E:\Matlab2014a\Matlab2014aInstall\extern\lib\win64\microsoft\libmx.lib\        E:\Matlab2014a\Matlab2014aInstall\extern\lib\win64\microsoft\mclmcr.lib\        E:\Matlab2014a\Matlab2014aInstall\extern\lib\win64\microsoft\mclmcrrt.lib\        E:\Matlab2014a\Matlab2014aInstall\extern\lib\win64\microsoft\libmat.lib\        E:\Matlab2014a\Matlab2014aInstall\extern\lib\win64\microsoft\libmex.lib\        E:\Matlab2014a\Matlab2014aInstall\extern\lib\win64\microsoft\libeng.lib\        F:\VSFiles\QtFiles\MatlabTest\libmyFunc.lib



(3)下面就是测试程序部分了

int MainWindow::ClickToShow(){   // 此处调用Matlab函数    libmyFuncInitialize();      double _x[5] = {1,2,3,4,5};    double _y[5];    mxArray *im = mxCreateDoubleMatrix(1,5,mxREAL);    mxArray *out = mxCreateDoubleMatrix(1,5,mxREAL);    memcpy(mxGetPr(im),(void *)_x,sizeof(_x));    mlxMyFunc(1,&out,1,&im);    memcpy(_y, (double*)mxGetPr(out), sizeof(_y));    libmyFuncTerminate();    QString ResultShow = QString::number(_y[2]);    QMessageBox::information(NULL,"OK",ResultShow);    return 1;}
我这里将测试程序写在了一个按钮的槽函数里面,便于测试,大概的框架就是先调用库初始化函数:libmyFuncInitialize(),然后调用我们的功能函数mlxMyFunc(),最后调用结束时使用libmyFuncTerminate()函数

如果程序没什么问题,那么结果应该是这样的:



但是,在这个过程中,我遇到了一个纠结了四五天的问题,同样的程序,放在VS2013里面,输出结果就正常,但是放在Qt里面虽然编译通过(当时我还不知道要把.ctf文件放到.dll目录下面),但是结果一直是0,我翻查了国内外很多网页都没有找到直接的答案。

搞技术只要坚持一定会有答案的,这不是真理,这是信念。

在各种调试之后,我把问题锁定在了初始化方面,因为libmyFuncInitialize()函数是bool类型,在VS里面返回值是true,但是在Qt里面是false,我查了很多网页,发现跟初始化相关的我们能操作的只有.ctf文件了,然后我就把.ctf文件放在跟.dll文件相同的目录下面,终于,我成功地连编译都出问题了:



程序这么简单,我们能操作的很少,这种异常实在不知道从何处下手,然后就继续翻网页,网页上说有可能是Qt调试器的问题,我就没有点击调试,直接运行程序了一下,然后整个世界都亮了,结果是正确的。但是调试就依然不行,而调试总是有必要的,解决放案如下:

工具->选项->调试器



把C++异常的勾号取消,然后点击Apply就可以了。

没错,就是在将近有几百个异常的情况下跑出来的正确答案,至于这些异常如何根除,我们这里就无法操作了。

VS和Matlab的混合编程相较而言是更简单实现的,这里就不多作介绍了,如果有问题可以评论联系我。