读了一些混合编程的程序,然后由于项目需要,写了一些代码,但并没有看过混合编程方面的书籍,故讲解的不够全面及深入。
在入门篇里讲解了环境的搭建及演示了一个hello word!程序:
#include <mex.h>
void mexFunction(int nlhs ,mxArray *plhs[] ,int nrhs, const mxArray *prhs[])
{
mexPrintf("Hello word!");
}
程序很简单,但和我们平常写的C程序并不一样,
程序必须包含mex.h头文件。
C的入口函数为mexFunction相当于我们常写的main函数,此函数没有返回值,必须是void型。
nlhs 为函数输出的个数,plhs为函数输出值,
nrhs 为函数输入的个数,prhs为函数参数值。
举例:
如.m函数为 function [x,y]=shiftX(a,b,c)
则在写成C语言,nlhs为2,plhs为x,y,nrhs为3,prhs为a,b,c
C函数如何引用参数:
如果是数组则用mxGetPr(prhs[loc]) //loc是参数的位置,如是第一个参数则为0,如第二个则为1
如果是单个数值mxGetScalar(prhs[loc])
如果是多维数组并不能用Arr[i][j]的格式寻址,在参数在C里只是一维数组,
一维数组按列排列,C语言是按行排列的,
如[a b c d;e f g h]C语言在内存中是按a b c d e f g h排列,而matlab是按 a e b f c g d h排列的。
如果要变成C语言可Arr[i][j]索引的格式,可用for循环转化,下面举个三维的例子:
for(i=0;i<inM;i++)
for(j=0;j<inN;j++) {
inYr[i][j] = inY[j*inM+i];
inYg[i][j] = inY[inM*inN+j*inM+i];
inYb[i][j] = inY[2*inM*inN+j*inM+i];
}
转化前,只可以按inY[loc]索引,转换后可以按inYr[i][j]格式索引。
打印函数:
mexPrintf()相当于matlab的disp函数,
mexPrintf函数里需要打印的部分必须用""而不能用\'\'
子函数的问题:
子函数有两种方式,一种采用return值得方式返回值
另一种方式为利用参数返回值,把需要return的值直接赋给形参。
多个.c文件的编译:
多个.c文件中只能存在一个mexFunction函数
可用mex (\'a.c\',\'b.c\',\'d.c\')的格式编译
下面是我写的C函数的一部分:
#include "mexSmoothL.h"
#include "mexfunc.h"
#define IN_Y prhs[0]
#define IN_M prhs[1]
#define IN_N prhs[2]
#define IN_K prhs[3]
#define OUT_L plhs[0]
void mexFunction(int nlhs ,mxArray *plhs[] ,int nrhs, const mxArray *prhs[])
{
double *inY,*matmns;
int i,j,k,l,m,n,inN,inM,inK,row,col;
double **inYr,**inYg,**inYb,**maxt,**numk,***uk,****covk;
double eye[3][3]={{1,0,0},{0,1,0},{0,0,1}},**midv1,**midv2;
inY = mxGetPr(IN_Y);
inM = (int)mxGetScalar(IN_M);
inN = (int)mxGetScalar(IN_N);
inK = (int)mxGetScalar(IN_K);
OUT_L=mxCreateDoubleMatrix(1,inN,mxREAL);
//matmns = mxGetPr(plhs[0]);
inYr=malloc2Ddouble(inM, inN);
inYg=malloc2Ddouble(inM, inN);
inYb=malloc2Ddouble(inM, inN);
numk=malloc2Ddouble(inM, inN);
uk=malloc3Ddouble(inM, inN,inK);
covk=malloc4Ddouble(inM, inN,inK,inK);
for(i=0;i<inM;i++)
for(j=0;j<inN;j++) {
inYr[i][j] = inY[j*inM+i];
inYg[i][j] = inY[inM*inN+j*inM+i];
inYb[i][j] = inY[2*inM*inN+j*inM+i];
}
maxt=malloc2Ddouble(9, inK);
midv1=malloc2Ddouble(inK, inK);
midv2=malloc2Ddouble(inK, inK);
matmns = malloc1Ddouble(inK);
for(row = 0;row<inM;++row)
for(col = 0;col<inN;++col) {
l=0;
for(i=max(0, col-RR);i<=min(inN-1, col+RR);i++)
for(j=max(row-RR, 0);j<=min(inM-1, row+RR);j++) {
maxt[l][0]=inYr[j][i];
maxt[l][1]=inYg[j][i];
maxt[l][2]=inYb[j][i];
l++;
}
numk[row][col]=l;
mat_mns(maxt, matmns, l, inK);
for(j=0;j<inK;j++)
uk[row][col][j]=matmns[j];
mat_cov(maxt, midv1, l, 3);
mat_add_mat(midv1, eye, epp/l, 3, 3);
mat3_inv(midv1, midv2, 3);
for(i=0;i<3;i++)
for(j=0;j<3;j++)
{
covk[row][col][i][j] = midv2[i][j];
mexPrintf("%f ",midv2[i][j]);
}
}
free(maxt);
free(matmns);
}