Using MEX-Files to Call C/C++ and Fortran Programs

From ift

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:

To understand how to use MEX-Files to Call C/C++ and Fortran Programs see

Tips 'n' Tricks

  1. 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">

  1. include "mex.h"
  2. 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>