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.
#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);
}