Creating MEX files - Part 1

I've recently been working on some slightly more elaborate codes that are quite time intensive (several hours). When I took a look at the results running the profiler, I found that the majority of this time was being consumed by a single function that contained a quite large, yet unavoidable FOR loop. In these cases, it makes sense to try and dig out your old C books and have a go at making a MEX file.

I am no C programmer. I can just about work out what a block of C code is doing if I need to reproduce an algorithm but I see and use it so infrequently that I am certainly at level basic. The following is provided as a kind of beginners guide to how MEX functions work for those who don't really know a great deal about C.

To start with, we are going to create a MEX file that takes an MxN array of doubles and outputs them to file with a user defined separator.

The basics of a MEX file looks like this:

void mexFunction(
int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
/* C code goes here */
}

What does this mean?

  • void mexFunction: the name of the gateway routine; Basically a wrapper function that tells MATLAB to get ready to work with C code
  • int nlhs: 'number of parameters, left hand side'
  • mxArray plhs: an array of 'parameters, left-hand side'. In other words, the function outputs just like you'd see on the left hand side of any function definition in a standard .M file
  • int nrhs: 'number of parameters, right hand side'
  • mxArray prhs: an array of 'parameters, right-hand side'. In other words, the function inputs just like you'd see on the right hand side of a function definition in any standard .M file

Now for the C code. Open a blank text file called 'dumptofile.c'. Our first few lines will now tell MATLAB which libraries must be included in order for our MEX file to work. We don't need any extra libraries here. Put the following lines to your file:

#include "mex.h"
void mexFunction(
    int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    /* C code goes here */
}

The first line is extremely important in that it gives us access to the mx* and mex* routines that we will use to communicate with MATLAB.

All that is left to do now is add the necessary C code to get the input parameters (prhs) and loop through the array of doubles. Take note of the functions that are used that begin 'mx'; these are functions that are specific to MEX files. If you can't work out what they are doing, I suggest you take a bit of time to do some reading on each of them.

#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{  
// ============================================
// 			Declarations
// ============================================
    mxArray *inputArrayData;    // array for input array pointers
    double  *inputArrayValues;  // input array
    mxArray *filepathData;      // array for filepath pointers
    int      filepathLength;    // length of the filename in characters
    char    *filepath;          // path for output file
    mxArray *seperatorData;     // array for seperator pointers
    int seperatorLength;        // length of seperator
    char *seperator;            // seperator
    int M, N;                   // dimensions of the input array
    int i,j;                    // counters for looping through array
    double value;               // variable to hold array value
    FILE *fid;                  // File identifier
    
    /* Check number of input arguments */
    if(nrhs!=3) {
        mexErrMsgTxt("Three arguements are required for dumptofile") ;
    }
    /* Check first input argument is numeric */
    if(!mxIsNumeric(prhs[0]) ) {
        mexErrMsgTxt("First input must be numeric") ;
    }
    /* Check second input argument is a string (filepath) */
    if( mxIsChar(prhs[1]) != 1) {
        mexErrMsgTxt("Second input must be a string") ;
    }

    // copy pointers
    inputArrayData = prhs[0];
    filepathData   = prhs[1];
    seperatorData  = prhs[2];

    // Get input array and its dimensions
    inputArrayValues = mxGetPr(inputArrayData);
    M = mxGetM(inputArrayData);
    N = mxGetN(inputArrayData);

    //Get the filename
    filepathLength = mxGetN(filepathData)+1;
    filepath = mxCalloc(filepathLength, sizeof(char)); //mxCalloc is similar to malloc in C
    mxGetString(filepathData,filepath,filepathLength);
    
    // Get the seperator
    seperatorLength = mxGetN(seperatorData)+1;
    seperator = mxCalloc(seperatorLength, sizeof(char)); //mxCalloc is similar to malloc in C
    mxGetString(seperatorData,seperator,seperatorLength);
	
    // Try and create the file
    fid = fopen(filepath, "wt");
	
    // print in the order they are in memory
    for(i=0; i < M; i++) {
        for(j=0; j < N; j++) {
            // Get the corrisponding value
            value = inputArrayValues[i + j*M];
            // Write the value to file
            fprintf(fid, "%f",value);
            if (j < N-1) {
                fprintf(fid, "%s",seperator);
            }
        }
        fprintf(fid, "\n");
    }
    // Close the file
    fclose(fid);
}

Now we need to turn this C code into a MEX file. Open MATLAB and make sure dumptofile.c is in the working directory. On the command line, run "mex dumptofile.c". This should produce a new file with an extension that looks something like ".mexw32".

That's it. Lets test it by comparing it to dlmwrite::

double_array = rand(10000,1);

tic
dlmwrite('C:\output\test.txt', double_array, ',');
times.dlmwrite = toc;

tic;
dumptofile(double_array, 'C:\output\test.txt', ',');
times.dumptofile = toc

Did you find this useful? Do you have comments on how it could be improved? Please leave your comments below

I assumption a animal

I assumption a animal mathematician interprets the aboriginal band as agnate to the second 350-040, but computers , and computer geeks like Bill Gates, accede the aboriginal as agnate to the third 350-050. Too bad this blog glossed over the “dissection” of the adding and just larboard it as Wolfram Alpha right; Bill Gates wrong, but hey I assumption I can “do mathematics” too 640-801.

good written

this is a nice post i like that thing :)
The first problem is that the E20-340 exam line 'one in a million' is intended to highlight how unique you feel that a special someone is. However, there PW0-104 exam are an infinate number of things that make will make a person unique. Yet, these differences do not necessarily mean unique in a good 70-642 exam way. They can in fact mean quite the opposite.

Thanks a lot for sharing

Thanks a lot for sharing such a good code.I am doing work in Mat lab for the designing of Patch antenna.after engg. i ma doing my mba.There is project for me making a software about cheap insurance.Is it possible in Mat lab.