C++和Matlab混合编程——VS调用Matlab函数

时间:2022-09-22 09:20:29

第一次自己动手写,实际上需求是很简单,就是在我的c++程序里调用matlab里的统计函数tinv。

看了很多教程,很小的一个问题,一个晚上才解决。。。浪费了不少时间,总结一下。

(1)环境配置搭建

matlab配置:开始前matlab需要先安装两个编译插件,这个安装直接在matlab命令窗口中敲入分别输入命令:

mex -setup;
mbuild -setup

安装过程中可以直接回车,或者根据控制台返回的指令,选择对应的自己的编译器。

vs配置:我这边用的是VS2010,但是感觉好像编译器版本什么的影响不是很大。

1.配置c++程序中的包含目录、库目录这个对应于你的电脑matlab的安装位置分别把.h和lib文件指向..\extern\include、..\extern\lib\win64\microsoft.
2.在 链接器->附加依赖项 中加入所需的库libmx.lib、 libmat.lib、libeng.lib,以及调用mwArray所需的类的库mclmcrrt.lib,mwArray是连接c++与matlab所需的 矩阵类,如果不懂这个类的使用需要先网上查看一下用法。
3.同时还要在系统坏境变量中,添加matlab的动态链接库.dll文件所在的位置,这个就在matlab安装位置的bin目录下。

【实际上这边正常情况下就配置好了,但是我之后一直遇到的问题也是由于vs的配置,所以先直接在这边说明。】

因为我的系统是64位的,所以刚才上述的配置并不够。需要做下面的步骤:
C++和Matlab混合编程——VS调用Matlab函数
就是图片位置里的win32,改成x64。注意:改完之后也要记得将上面的包含目录、库目录以及相关的链接库配置好。这边会自动生成对应的release和debug的属性管理器,进入直接配置即可。

(2)相关文件生成
上面配置结束之后,可以根据自己的需求,开始生成相关的文件。

首先在matlab里面,对于我要调用的函数,先生成相关的库文件等。语句如下:

mcc -C -W cpplib:Find_T_ValueLib -T link:lib find_t_value.m

这边注意一下,应该是C和C++的区别,我没有深究,这边用的是cpplib才能生成后面所需的.ctf文件,如果用的是lib指令,该文件无法生成。

将上面matlab语句中生成的.ctf,.dll,.h,.lib文件拷贝到C++工程目录下,然后在c++中加入头文件.h,后面就可以调用了。我现在还没开始写,明天试试看。

效率太低了,该死。

今天已经是第二天了,终于把问题解决了,然而这个原因真的蛋疼地让我想切腹。这么久以来,一直报mwException异常的原因是我的函数里面调用的数据类型问题。。。气死了,下面好好说一下。

上面的配置完成后,我调用我的函数,代码如下:

int left_p = waittime_eachsimulation.size()-1;
double right_p = 1-alpha/2;
if(!libTinvInitialize())
    return -1;
mwArray par1(1,1,mxINT32_CLASS);
mwArray par2(1,1,mxDOUBLE_CLASS);
mwArray res(1,1,mxDOUBLE_CLASS);
par1.SetData(&left_p,1);
par2.SetData(&right_p,1);
double cc=res.Get(1,1);

这边对于两个参数分别使用了int和double类型,因为参数本身就是该类型,并且在matlab里使用的时候也是这样的,我就认为没有问题。结果最终发现问题就出在这里。这样就是不行的。好像是在matlab的tinv的函数里,那个整数也是需要为double类型的。

然后就报这样的错C++和Matlab混合编程——VS调用Matlab函数

我一开始就在想到底是我数据类型的问题还是函数调用的问题,因为使用的是mwArray的数据类型,我不知道怎么看我的参数是不是真的传进去了,所以浪费了很多时间。

中间学了一招,就看出错原因。就是用异常捕捉语句。
如下:

try
{
    tinv(1,res,par2,par1);//这是我dll里的函数
}
catch (const mwException& erro)
{
string str;
str = erro.what();
cout<<str<<endl;
}

在catch语句里将你需要看的异常定义一个对象,后面输出即可。而且这边很重要的一点是,在混合编程的时候,要先调用libTinvInitialize()这个函数,因为我在操作的时候发现,如果不调用这个函数,直接去捕捉异常的话,得到的结果只有invalid input,但是一旦调用了该初始化函数,得到的异常结果就比较清楚,还是用中文说明的错误使用+,整数只能与相同类的整数或标量双精度值组合使用,我也不晓得为啥,反正以后记得就行了。

这是问题发现的过程,后面把对应的数据类型都改成double,然后代码就能跑通了。真的是浪费了一天的时间啊。。。晚上开始好好写报告加习题把。