最近的项目须要matlab和C的混合编程,通过一番努力终于完成了项目要解决的问题。如今就将Mex的一些经验总结一下,固然只是刚刚开始,之后随着学习的深刻继续添加。首先讲讲写Mex的一些常规规定,而后咱们会重点关注混合编程中最难解决数据的问题--结构到底如何转换,而且后面会重点说一下本身的程序。html
1、Mex的结构c++
先看一个简单的程序(该程序保存在matlab主目录下名字是mexDemon.cpp,或者在主目录下新建一个.cpp文件):编程
#include "mex.h" //加入头文件,该头文件在VS2010中没法include,可是不影响其在matlab中的编译,反而在matlab编译还须要include它 #include <vector> using namespace std; void mexFunction(int nlhs, mxArray *plhs[],int nrhs,const mxArray *prhs[]) //mexFunction就相似于main函数 { //nlhs表明的是输出参数的个数 //plhs是一个指针数组,里面的指针指向mxArray类型,每个指针指向一个输出 //nrhs表明的是输入参数的个数 //prhs是一个指针数组,里面的指针指向mxArray类型,每个指针指向一个输入 vector<vector<double> > array2d; double *z; plhs[0] = mxCreateDoubleMatrix( 5, 6, mxREAL);//第一个输出是一个5*6的矩阵 z = mxGetPr(plhs[0]);//得到矩阵的第一个元素的指针 array2d.resize(5); int ii = 0; for(int i = 0; i < 5; i++){ for(int j = 0; j < 6; j++){ z[i*6 + j] = ii; //指针访问矩阵是列优先的,请本身循环程序和分析输出结果 ii++; } } } /* *ans = 0 5 10 15 20 25 1 6 11 16 21 26 2 7 12 17 22 27 3 8 13 18 23 28 4 9 14 19 24 29 */
而后对Matlab编译应用程序mex的编译器进行设置,在命令窗口输入 Mex –setup。 而后跟着步骤走选择合适的编译器便可。数组
设置完编译器以后在命令窗口输入Mex mexDemon.cpp 进行编译生成.mexw64文件,生成以后即可以直接调用了,例如本例子能够这样调用,就是直接在命令窗口输入 a = mexDemon(); 返回值如上。缓存
2、C和Matlab的数据结构的转换数据结构
(1)数值的传递函数
matlab -> c++学习
x = mxGetScalar(prhs[0]);//该函数获取matlab传递过来的数值;
c++ -> matlabspa
plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);//建立返回的矩阵,范围plhs[0]为mxArray类型 y = mxGetPr(plhs[0]);//获取返回plhs[0]的数据地址,其后能够修改y的值就能够返回了
一个实例(numDemon.cpp):指针
#include "mex.h" void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ int x = mxGetScalar(prhs[0]); //将第一个输入参数转为Scalar标量,也就是单数值 printf("%d\n", x); //打印 double *y; plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL); //让第一个输出参数指向一个1*1的矩阵 y = mxGetPr(plhs[0]); //得到矩阵的第一个元素的指针 *y = 10; //将其赋值为10 }
以下图在命令窗口编译:
(2)矩阵的传入与传出
关于传出(c++到Matlab, 就是第一个例子),下面能够再给一个例子是如何从matlab传入到c++,看下面这段代码:
#include "mex.h" void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ double *dataCursor; vector<vector<double> > parms; dataCursor = mxGetPr(prhs[0]); //获得输入矩阵的第一个元素的指针 int mrows = mxGetM(prhs[0]); //得到矩阵的行 int ncols = mxGetN(prhs[0]); //得到矩阵的列 printf("%d_%d\n", mrows, ncols); //打印行和列 parms.resize(mrows); //初始化 for(int i = 0; i < mrows; i++){ parms[i].resize(ncols); } for(int i = 0; i < mrows; i++){ for(int j = 0; j < ncols; j++){ parms[i][j] = dataCursor[j * mrows + i]; //拷贝矩阵的元素到vector of vector } } }
一样在命令窗口编译便可。
(3)字符串的传入与传出
matlab -> c++ (传入)
char *input_buf; input_buf = mxArrayToString(prhs[0]);//使用mxArrayToString将mxArray转换为c、c++字符串
c++ -> matlab (传出)
char *output_buf;//定义字符串缓存 size_t buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1;//获取字符串长度,mxGetM获取行数,mxGetN获取列数 output_buf=mxCalloc(buflen, sizeof(char));//使用mxCalloc分配输出字符串数组 plhs[0] = mxCreateString(output_buf);//使用mxCreateString建立mxArray输出 mxfree(output_buf);
一个实例(strDemon.cpp)
#include "mex.h" void revord(char *input_buf, size_t buflen, char *output_buf) { mwSize i; if (buflen == 0) return; for(i=0;i<buflen-1;i++) *(output_buf+i) = *(input_buf+buflen-i-2); } void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { char *input_buf, *output_buf; size_t buflen; buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1; //由于本程序是翻转字符串,因此输入输出字符串的长度应该同样 output_buf=mxCalloc(buflen, sizeof(char)); //申请空间 input_buf = mxArrayToString(prhs[0]); //得到输入字符串 revord(input_buf, buflen, output_buf); //翻转字符串 plhs[0] = mxCreateString(output_buf); mxFree(input_buf); return; }
一样编译一下便可。
(4)cell的传入
#include "mex.h" void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ mwSize cellNdim = mxGetNumberOfDimensions(prhs[0]); //这里介绍两个函数mxGetNumberOfDimensions和mxGetDimensions const int *cellColPtr = mxGetDimensions(prhs[0]); //mxGetDimensions: 就是返回一个指针ptr,每个指针所指向的值是每个维度的元素个数。例若有矩阵3*2的矩阵,那么*(ptr)为3,*(ptr+1)为2. //mxGetNumberOfDimensions: 返回mxArray的维度。 int cellNRow = *(label_dims); int cellNCol = *(label_dims + 1); mxArray *ptr; ptr = mxGetCell(prhs[0], 0); //获取cell的第0个元素,返回一个mxArray指针,第二个参数表明cell中元素的下标 mxArray *cellOfCell; cellOfCell = mxGetCell(ptr, 0); //固然cell里面能够仍是cell,那么应该再样写 mxArray *cellOfStr; char *chTmp; cellOfStr = mxGetCell(prhs[0], 0); //固然cell里面能够是字符串 chTmp = mxArrayToString(cellOfStr); printf("%s\n", chTmp); }
后面待补充结构体和cell数组的传出,暂时还没遇到这样的需求。再贴上几个参考网址:
1.http://blog.sina.com.cn/s/blog_9db9f81901013yv2.html
2.http://blog.sina.com.cn/s/blog_80202a090100uhup.html