由图1.1可知,mexFunction为MATLAB调用MEX文件的接口函数,其格式为:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
参数nlhs和plhs[]分别为输出参数个数和输出数据,与MATLAB一般函数的左手侧参数(left-hand-side) 对应;nrhs和prhs[]分别为输入参数个数和输入数据, 与MATLAB一般函数的右手侧参数(right-hand-side) 对应;
MATLAB程序中最基本的数据类型是矩阵和数组,而C程序中数据类型有整型int、单精度float、双精度double、字符串string、结构体struct及数组等。因此,基于接口函数的MATLAB程序与C程序间数据交换,最重要的是不同类型数据间的传递。为此,MATLAB提供了一个特殊的C语言结构-mxArray,以在C语言中表示MATLAB的矩阵和数组。在MEX文件的接口程序中,输出参数plhs[]和输入参数prhs[]均为mxArray定义的对象。MATLAB在调用MEX文件时,将数据传给mexFunction的输入参数prhs[],mexFunction在返回MATLAB之前,将C程序的计算结果传入输出参数plhs[]中,实现MATLAB与C程序数据交换。此外,由于MATLAB与C语言的内存管理机制不同,MEX文件编写过程中,应统一应用MATLAB内存管理机制,即在接口程序与用户C程序中,内存的分配与管理,均采用mx内存管理函数,如C程序中malloc、realloc、calloc和free函数,一般以mxMalloc、mxRealloc、mxCalloc和mxFree函数代替。
综上,我们编写了第一个MEX文件“h1.c”来开始学习如何使用MATLAB提供的API。
/////////////////////MEX头文件////////////////////////////////////////////
#include "mex.h"
////////////////////用户C程序 /////////////////////////////////////////////
double OutPut(int n,double *rP)
{ int i; double *sum,sum0;
FILE *fp1;
sum=mxCalloc(1,sizeof(double));//////////////////内存在管理机制为MATLAB机制
if((fp1=fopen("OutPut1.txt","w"))==NULL){ mexErrMsgTxt(" Can't open OutPutfile\n");}
*sum=0.0;
fprintf(fp1,"Input %d Data is:",n);
for(i=0;i<n;i++){*sum=*sum+rP[i];fprintf(fp1," %7.2lf ",rP[i]);}
fprintf(fp1,"\nsum= %7.2lf \n",*sum);
fclose(fp1);
sum0=*sum;
mxFree(sum);//////////内存在管理机制为MATLAB机制
return sum0; /////// C程序返回计算值
}
////////////////// 接口程序mexFunction/////////////////////////////////////
void mexFunction(int nlhs,mxArray *plhs[],int nrhs, mxArray *prhs[])
{int i; double *rP,*lP,sum;
////////////////// 由 prhs[] 中取得MATLAB输入数据
rP=mxCalloc(nrhs,sizeof(double));///////////内存在管理机制为MATLAB机制
for(i=0;i<nrhs;i++)rP[i]=mxGetScalar(prhs[i]);
///////////////// 调用C程序
sum=OutPut(nrhs,rP);
//////////////// 进行数据类型转换,并存入 plhs[] 返回MATLAB
nlhs=nrhs;
plhs[0]=mxCreateDoubleMATrix(1,nlhs,mxREAL);
lP=mxGetPr(plhs[0]);
for(i=0;i<nlhs;i++)lP[i]=i*sum;
mxFree(rP); ///////////内存在管理机制为MATLAB机制
mxFree(lP);
}
///////////////////结束//////////////////////////////////////////////////////
该程序包括以下几部分:
(1)MEX程序的头文件“mex.h”;
(2)用户C程序OutPut();
(3)接口程序mexFunction()。
MATLAB在调用该MEX文件时,首先H1.c中寻找接口函数mexFunction(),并将数据传至mexFunction的输入参数prhs[],由于prhs[]是由mxArray定义的指针型数组,MATLAB将输入参数地址赋给prhs[],将输入参数个数赋给nrhs,用户无须对prhs[]赋起始地址。并且,MATLAB提供了一系列函数来获取输入参数prhs[]的地址和数据。如本例中,mxGetScalar()函数来获取prhs[]中标量,并赋给C语言双精度实型一维数组rP。
对于输出参数plhs[],接口函数mexFunction参数列表中仅对其数据类型进行了定义,但mexFuntion未给参数plhs[]赋地址,用户在使用该参数前须赋起始地址。如本例中,以mxCreateDoubleMATrix将plhs[0]赋为mxArray双精度实型矩阵指针,所指向矩阵行数为1,列数由输入参数nrhs个数确定。由于plhs[]为mxArray定义的指针数组,MATLAB提供也提供了一系列函数以便用户将数据赋给plhs[]。如本例中mxGetPr()函数将plhs[0]起始地址赋给C语言的双精度实型一维数组lP,只要用户将所得数据赋给lP,mexFunction函数通过plhs[0]将数据从MEX文件中输出至MATLAB,实现数据交换。
在MATLAB命令窗口中将“h1.c”文件编译后,得动态链接子程序h1.dll,并在MATLAB命令行中调用。
>>mex h1.c
>>a=h1(1,2,3,4,5)
a=
0 15 30 45 60
同时,由于用户C程序中执行了文件输出,在当前目录下生成“OutPut1.txt”文件,输出结果为:
Input 5 Data is: 1.00 2.00 3.00 4.00 5.00
sum= 15.00
以不同参数调用h1.dll,如
>> b=hh1(2,4)
b =
0 6
当前目录下生成“OutPut1.txt”文件,输出结果为:
Input 2 Data is: 2.00 4.00
sum= 6.00