A MEX függvények írásához egy egyszerű c++ kódot írunk .cpp kiterjesztésű fileba.
A MATLAB-ból hívott függvénynek fix fejléce van, ami valahogy így néz ki:
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
A függvény fejléce - bár érdekes betűkombinációkat tartalmaz - nem túl bonyolult. Konkrétan négy vátozót kapunk a MATLAB-bül amiket kezelnünk kell.
- nlhs: A bemeneti paraméterek száma;
- plhs: Pointer a bementei adatokat leíró tömbre. Minden adathoz kapunk egy mxArray típusú struktúrát, amiből kiolvashatjuk, hogy milyen és mekkora tömböket kaptunk (ugye a MATLAB-ban, minden tömb), és hogy azok tartalma hol van a memóriában.
- nrhs: A kimenetek száma;
- prhs: Pointer a kimenetek tömbjére. Ugyanúgy működik mint a bemeneteknél.
Tehát gyakorlatilag megkapjuk egy tömbben a bemeneteket, és egy tömbben a kimeneteket, amiknek kezeléséhez találunk függvényeket a mex.h függvénykönyvtárban. A programozás innentől kezdve csak az adatok kezelésében új.
Először érdemes leellenőriznünk, hogy jó adatokat kaptunk-e. Ha nem, akkor adunk egy hibaüzenetet.
if(nrhs != 2) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs",
"Two inputs required.");
}
if(nlhs != 1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs",
"One output required.");
}
if( !mxIsDouble(prhs[0]) ||
mxIsComplex(prhs[0])) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notDouble",
"Input multiplier must be type double.");
}
if( !mxIsDouble(prhs[1]) ||
mxIsComplex(prhs[1])) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notDouble",
"Input matrix must be type double.");
}
if(mxGetM(prhs[0]) != 1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector",
"First input must be a row vector.");
}
if(mxGetM(prhs[1]) != 1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector",
"Second input must be a row vector.");
}
if(mxGetN(prhs[0]) != mxGetN(prhs[1])) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector",
"Two input must have the same size.");
}
Ha minden rendben volt, akkor rátérhetünk a programra. A Matlab api-n k eresztül elkérhetjük a bemeneti paraméterek adataira mutató pointereket.
double *inVector1 = mxGetPr(prhs[0]);
double *inVector2 = mxGetPr(prhs[1]);
Ugyancsak lekérdezhetjük a mátrixok elemszámát
mwSize N;
N = mxGetN(prhs[0]);
Elkészíthetjük az eredményeknek szánt kimeneti tömböt.
double *outVector;
N = mxGetN(prhs[0]);
plhs[0] = mxCreateDoubleMatrix(1,N,mxREAL);
outVector = mxGetPr(plhs[0]);
És végül elindíthatjuk a számítász, amit ebben az eserben az arrayAdd(...) függvényben valósítottunk meg.
arrayAdd(inVector1,inVector2,outVector,N);
A függvény egyszerű elemenkénti összeadást valósít meg. Valójában még arról sem tud, hogy mátrixokat ad össze. A bemenetek tömbjeiben az adatok egymás mögé vannak felfízve, így feldolgozhatóak vektor-ként is.
void arrayAdd(double *x, double *y, double *z, mwSize n)
{
mwSize i;
for (i=0; i<n; i++) {
z[i] = x[i] + y[i];
}
}