Using MEX-Files to Call C/C++ and Fortran Programs
Understanding MEX
MEX-files (MATLAB executables) are used to call large pre-existing C/C++ and Fortran programs from MATLAB without translating them into MATLAB. Another advantage is that C/C++ code is generally faster than MATLAB.
The best source of information is MathWorks' knowledge database.
To understand C/C++ Source MEX-Files and to see how to compile them see:
- C/C++ Source MEX-Files (last checked 10 Jan 2011)
To understand how to use MEX-Files to Call C/C++ and Fortran Programs see
- Using MEX-Files to Call C/C++ and Fortran Programs (last checked 10 Jan 2011)
Tips 'n' Tricks
- Where to place the gateway routine within the C/C++ program
- The whole code can be placed in the Gateway routine
- At the end - it looks like the gateway routine should be the last routine in the code if more routines are present. This sheds the problem with undefined variables and alike. I (GG) haven't found any place in the knowledge base where this is mentioned. Maybe it is not true in all cases either. Here follows an example that is a modification of the original MATLAB code from the knowledge database (see link "MEX-Files to Call C/C++ and Fortran Programs" above). In the case below three input parameters are required, while in the original code only two are necessary. A comparison between the two version helps to find the in-s and out-s.
<source lang="cpp">
- include "mex.h"
- include "matrix.h"
/*
* arrayProduct.c * Multiplies one input scalar times a 1xN matrix, times another input scalar * and outputs a 1xN matrix * * This is a modified version of the MEX-file from MathWorks' knowledge database. * http://www.mathworks.com/help/techdoc/matlab_external/f29502.html * * The modifications are (LINE REFERENCES DIFFERENT FROM ORIGINAL): * the original "double multiplier" is replaced with "double multiplier1" (line 61) * introduced "double multiplier2" (line 62) * line 37 - added "double w" * line 42 - added " * w " * line 73 - changed message to be displayed * line 98, 99 - added those lines * line 113 - added "multiplier2" and changed "multiplier" with "multiplier1" */
/**************************************************/ /**************************************************/ /************* SOME ROUTINE *************/ /**************************************************/ /**************************************************/ /* Multiplies an input scalar times a 1xN matrix */ /* and output is a 1xN matrix */ /**************************************************/ /**************************************************/
void arrayProduct(double x, double *y, double *z, double w, mwSize n)
{
mwSize i; for (i=0; i<n; i++) { z[i] = x * y[i] * w; }
}
/**********************************************************/
/**********************************************************/
/************* THE GATEWAY FUNCTION *************/
/**********************************************************/
/**********************************************************/
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
/*** Variable declarations ***/
double multiplier1; // input scalar double multiplier2; // input scalar double *inMatrix; // 1xN input matrix mwSize ncols; // size of matrix double *outMatrix; // output matrix
/*** CODE ***/
// check for proper number of arguments if(nrhs!=3) { mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs", "Three inputs required."); } if(nlhs!=1) { mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs", "One output required."); }
// make sure the first input argument is scalar if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || mxGetNumberOfElements(prhs[0])!=1 ) { mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notScalar", "Input multiplier must be a scalar."); }
// check that number of rows in second input argument is 1
if(mxGetM(prhs[1])!=1) { mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector", "Input must be a row vector."); }
// get the value of the first scalar input multiplier1 = mxGetScalar(prhs[0]);
// get the value of the second scalar input multiplier2 = mxGetScalar(prhs[2]);
// create a pointer to the real data in the input matrix inMatrix = mxGetPr(prhs[1]);
// get dimensions of the input matrix ncols = mxGetN(prhs[1]);
// create the output matrix */ plhs[0] = mxCreateDoubleMatrix(1,ncols,mxREAL);
// get a pointer to the real data in the output matrix outMatrix = mxGetPr(plhs[0]);
// call the computational routine arrayProduct(multiplier1,inMatrix,outMatrix,multiplier2,ncols);
}
</source>