mex的适用情况:需要大量循环或者遍历,不想改写已有的C模块,这些情况下适用mex接口比较合适。
mex的环境要求:已安装MATLAB,已安装合适的C编译器。
mex使用:
首先在MATLAB中使用mex -setup设置工作环境和相应的配置文件。mex其他参数详见帮助。
对于需要使用mex接口的程序,文件的扩展名需要为c/cpp,然后用mex
filename进行编译。编译完成后会生成dll文件(7.1之前)或者mexw32文件(7.1之后)。
编译完成后,即可像m文件一样适用mex。
mex接口的结构:
//
#include "mex.h"
///
// Computational Routine //
///
// interface & function
declaration
return_type myFunc1(parameter1,
parameter2, ...);
return_type myFunc2(parameter1, parameter2, ...);
...
// interface & function
defination, implementation
void myMex(parameter1, parameter2,
...){
statements
}
return_type myFunc1(parameter1,
parameter2, ...){
statements
}
return_type myFunc2(parameter1,
parameter2, ...){
statements
}
...
/
// Gateway Routine //
/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray
*prhs[]){
...
myMex(parameter list);
}
//
调用mex时,MATLAB将输入的数据通过入口子程序赋给输入参数指针,同时创建由输出参数指针指向的输出矩阵,然后将这些指针作为计算子程序的参数传递到计算子程序进行计算。
mexFunction在调用C函数时,直接使用指针传递参数是比较方便的,一方面需要计算的结果往往是一个矩阵而不是一个数,另一方面以值传递值返回的方式,同样需要赋值给mex接口的指针。
在mexFunction的参数中:
nlhs表示输出参数的个数
nrhs表示输入参数的个数
类型为mxArray的指针数组,用于指向输出的每个参数
类型为mxArray的指针数组,用于指向输入的每个参数
为了mex的正确执行,也是良好编程习惯的要求,需要对输入参数和输出参数进行个数和类型的检查:
mxGetClassID //获得指针所指变量类型
mxIsNumeric, mxIsCell等,检查指针所指变量是否为符合某种要求的变量类型。更多可查阅帮助。
参数检查过程中可使用mexErrMsgTxt输出错误信息。
mxGetM, mxGetN,获得矩阵的行数和列数
mxGetDimensions,获得矩阵维数
mxGetPr,mxGetPi,获得矩阵实数部分、虚数部分的指针
mxGetString, 获得字符串内容
mxGetElementSize, 获得存储矩阵元素所需要的字节数
mxCalloc,内存分配。用mxCalloc不用calloc和malloc,因为mxCalloc会自动释放内存,不需要手动free了。
mxCreateString, 创建1*N的字符串矩阵
mxCreateDoubleMatrix,
创建2维双精度浮点矩阵,可以是实数(mxREAL)或者复数(mxCOMPLEX)
mxCreateStructArray, 创建N维结构体矩阵
mxCreateCellMatrix, 创建二维单元矩阵
mxCreateNumericArray,创建n维数值矩阵
mexPrintf, 重新封装的printf
mxSetFiled, 设置结构体矩阵的域
mxSetCell, 设置单元矩阵的单元值
mxSetPr, 设置矩阵实数值
mxSetPi, 设置矩阵虚数值
mxCallMATLAB,
调用MATLAB中其他内建函数、自定义M文件、mex文件。
具体使用方法可查阅MATLAB帮助。
使用mex时的注意事项:
1.MATLAB调用mex接口时,将参数个数及参数指针传入接口子程序,由接口子程序完成指针和调用变量的赋值、输出数据的内存空间分配,接口子程序再将参数指针或经过赋值的变量作为参数传递给C的计算子程序,完成调用过程。调用时应注意指针所指对象的正确性,为处理正确最好做相应的强制类型转换。
2.mex并不便于调试,因此应在C的IDE中用测试集调试后再放入mex文件中。
3.MATLAB中指向二维及高维数组的指针递增方式是按行递增的,而C中是按列递增的,因此计算index时要注意位置。
下面给个我的例子:
/
#include "mex.h"
int LSB(int pixel);
int tier_score(int s_1,int s_2,int x_1,int x_2);
int add_sub_select(int pixel_1,int pixel_2);
void cost_matrix_gen_c(double *output,double *x,double
*len_x,double *y,double *len_y){
int
i,j;
int
s_1,s_2,x_1,x_2;
for
(j=0;j
x_1 = (int)*(y+j*2);
x_2 = (int)*(y+j*2+1);
for (i=0;i
s_1 = (int)*(x+i*2);
s_2 = (int)*(x+i*2+1);
*(output++)=tier_score(s_1,s_2,x_1,x_2);
}
}
}
int tier_score(int s_1,int s_2,int
x_1,int x_2){
int
score;
if
(s_1==LSB(x_1)){
if (s_2==add_sub_select(x_1,x_2)){
score = 20;
}
else{
score = 0;
}
}
else{
score = 0;
}
return
score;
}
int LSB(int pixel){
return
pixel%2;
}
int add_sub_select(int pixel_1,int
pixel_2){
return
LSB((int)pixel_1/2 + pixel_2);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray
*prhs[]){
double
*y,*x,*output,*len_x,*len_y;
int
n_row,n_column;
if (nrhs !=
4 || nlhs != 1){
mexErrMsgTxt("invalid number of input/output arguments!");
}
//参数个数检查
n_row = mxGetM(prhs[0])>mxGetN(prhs[0]) ?
mxGetM(prhs[0]) : mxGetN(prhs[0]);
//获得输入向量元素个数
n_column = mxGetM(prhs[2])>mxGetN(prhs[2]) ?
mxGetM(prhs[2]) : mxGetN(prhs[2]);
//获得输入向量元素个数
n_row = n_row/2;
n_column =
n_column/2;
plhs[0] =
mxCreateDoubleMatrix(n_row,n_column,mxREAL);
//建立n_row*n_column大小的输出矩阵
output =
mxGetPr(plhs[0]); x=mxGetPr(prhs[0]);
len_x=mxGetPr(prhs[1]);
y=mxGetPr(prhs[2]);
len_y=mxGetPr(prhs[3]);
//获得输入、输出指针
cost_matrix_gen_c(output,x,len_x,y,len_y);
//调用计算函数
}