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

网上虽然有一些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

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

>> !mcc
MCC 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 gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = MatlabTest
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h \
            libmyFunc.h

FORMS    += mainwindow.ui
OTHER_FILES += libmyFunc.ctf

INCLUDEPATH += E:\Matlab2014a\Matlab2014aInstall\extern\include\
               E:\Matlab2014a\Matlab2014aInstall\extern\include\win64

LIBS += 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的混合编程相较而言是更简单实现的,这里就不多作介绍了,如果有问题可以评论联系我。





  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值