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

From ift
Revision as of 07:58, 8 February 2011 by Gge002 (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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

}