在MATLAB中调用封装好的C++函数的方法

来源:互联网 发布:淘宝店铺取名字 编辑:程序博客网 时间:2024/06/06 07:45
背景

MATLAB有强大的矩阵运算能力以及丰富的函数库,可以用于算法的仿真以及快速验证某些算法思路。MATLAB的UI层是利用基于JVM利用Java实现的,而部分算法的底层则是封装了C/C++以及Intel提供的汇编指令集。因此MATLAB在用于计算时的速度是非常之快的。但是有的时候我们经常看到,虽然一些论文或者文章中描述了算法,并且作者也在个人主页上po处了源代码。但是这些算法的细节我们的是看不到的,可能是由于专利的原因,也可能是算法中的某些参数是经过了大量验证而作者并不想公布的。因此,对于很多图像类的算法,作者们都是采用了将算法的核心部分利用MATLAB自带的C编译器mexcc封装为一个.mexw64(64位系统)或.mexw32(32位系统)文件,然后在MATLAB的.m文件中通过函数名直接调用这些封装的函数。这样既保证了算法的速度,又可以保留必要的细节。那么如何实现这个呢?其实很简单,下文会详细介绍

方法

之前写过一篇关于如何在VS中调用MATLAB函数的方法,既要安装MATLAB RUNTIME COMPILER又要设置工程的附加库和包含目录,同时C和C++文件调用MATLAB还有区别,非常的麻烦。但是如果发过来,通过MATLAB来调用C/C++函数就相对而言过程简化了很多。

1. C++端的代码
为了方便,我们用一个简单的demo来举例子。假设我们需要封装原来的C++函数: 
// Arithmetic_Operation.cpp// 本函数实现了两个double型参数输入的四则运算,并保存在res数组中,顺序为加减乘除#include <cstdtio>void Arithmetic_Operation( double* res, double a, double b ){     res[0] = a + b;          res[1] = a - b;     res[2] = a * b;     res[3] = ( b == 0 ? 0 : a / b ) ; // check whether divide is zero          return;}

我们要将Arithmetic_Operation函数封装为一个.mexw64文件并在MATLAB中调用,具体的做法是:
新建一个.cpp文件,这里需要注意的是:
cpp文件名就是在MATLAB中编译了之后以供调用的函数名,所以请不要随意命名需要编译的cpp文件。
我们将文件名为ArithmeticOp.cpp

也就是说,在编译好了之后在MATLAB中调用方式是:

[ res ] = ArithmeticOp(a, b);

下面是ArithmeticOp.cpp文件的实现:
/* ArithmeticOp.cpp */#include "mex.h" //一定要包含这个头文件,这个头文件是MATLAB为MEX编译专门提供的头文件 #include <cstdio>// 被封装的函数声明void Arithmetic_Operation( double* res, double a, double b );/** 请注意下面的这个mexFunction函数,如果需要使用mex编译C++函数,一定要使用这个函数* mexFunction就像#include "mex.h"一样是必须的,相当于是MATLAB和C++的一个接口函数* 这个函数的四个参数都是有用的,它们分别代表的意思是:* nlhs: 输入参数个数(MATLAB调用语句中,等号左边的参数个数)  plhs: 输入参数列表* nrhs: 输出参数个数(MATLAB调用语句中,等号右边的参数个数) prhs: 输处参数列表*/void mexFunction( int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[] ){     if (nlhs != 1 || nrhs != 2 )// 判断调用参数数量是否正确     {          printf("Invalid Argument Usage!\n");          exit(0);     }          // get input data     double* a = mxGetPr(prhs[0]); // 输入参数列表,下标0是第一个输入参数     double* b = mxGetPr(prhs[1]); // 类似于C++ main函数的两个参数(int argc, char** argv)的使用     double* result = (double *)malloc(4*sizeof(double));          // invoke      Arithmetic_Operation(result, *a, *b);          // output data     plhs[0] = mxCreateDoubleMatrix(4, 1, mxREAL);// 用于创建一个double型的矩阵,三个参数分别是矩阵的行,列,类型     double* output = (double *)mxGetPr(plhs[0]); // mexGetPr()函数是mex.h中提供的用于获取输入输出参数地址的函数     for (int i = 0; i < 4; i++)          output[i] = result[i];     free(result);     return;}/* 被封装的函数 */void Arithmetic_Operation( double* res, double a, double b ){     res[0] = a + b;          res[1] = a - b;     res[2] = a * b;     res[3] = ( b == 0 ? 0 : a / b ) ; // check whether divide is zero          return;}// end of implementation

这样,一个简单的MATLAB调用C++函数的demo就写好了,如果读者需要使用并修改功能,就是直接修改mexFunction中的内容即可。更复杂的功能和函数都是可以的。

2. MATLAB端
上面复杂的C++代码都已经写好了,剩下的MATLAB的部分就相对容易了。
使用mexcc编译有一个必要的条件就是安装了VS编译器。
我的配置环境是MATLAB 2011b + VS2010 ultimate + win7-64bit

然后打开MATLAB的 Command Window
输入 
mex -setup

然后选择选择y

选择编译器1

再选择y ...

接下来就配置好了的。

接着我们编译刚才写好的ArithmeticOp.cpp文件
在MATLAB中输入 

mex ArithmeticOp.cpp

这样就会生成相应的ArithmeticOp.mexw64文件(根据系统位数决定)
然后复制一份.mexw64文件在MATLAB中的工作目录下,就可以正常的在MATLAB Command Window或者.m文件中调用了



几点注意事项

1. MATLAB和C++的交互中,接口的调用都是Double型的
2. plhs和prhs使用mxCreateDoubleMatrix()分配的内存是不用回收的,因为接口部分的内存信息是需要传递的
3. 在保持mexFunction()不变的情况下,其他所有的C/C++的功能与特性都是支持的。





0 0