Introduction
The MATLAB M-File is very good for putting together functions or scripts that run many of MATLAB's fast Built-In functions. One nice thing about these files is that they are never compiled and will run on any system that is already running MATLAB. MATLAB achieves this by interpreting each line of the M-File every time it is run. This method of running the code can make processing time very slow for large and complicated functions, especially those with many loops because every line within the loop will be interpreted as a new line, each time through the loop. Good MATLAB code avoids these things by using as many Built-In features and array operations as possible (because these are fast and efficient). Sometimes this is not enough...
MATLAB has the capability of running functions written in C. The files which hold the source for these functions are called MEX-Files. The mexFunctions are not intended to be a substitue for MATLAB's Built-In operations however if you need to code many loops and other things that MATLAB is not very good at, this is a good option. This feature also allows system-specific APIs to be called to extend MATLAB's abilities (see the Serial Port Tutorial for an example of this).
This document is arranged in the following manner:
- The MEX-Function: Interface to MATLAB
- Getting and Creating Data
- Calling Built-In Functions from a MEX-File
- Compiling
- Useful Functions not Mentioned Here
The MEX-Function: Interface to MATLAB
When writing programs in C, it is always assumed that the program will start execution from the main(). MEX -Files are similar in that they always start execution from a special function called the mexFunction. This function has return type void and is the "gateway" between the MATLAB function call, and your C code.
EXAMPLE 1
//You can include any C libraries that you normally use #include "math.h" #include "mex.h" //--This one is required void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { //All code and internal function calls go in here! return; }
In order to make a mex-function, you must include the "mex.h" library. This library contains all of the APIs that MATLAB provides. There are four input parameters to the mexFunction which correspond to the way a function is called in MATLAB - (ex:
[z0,z1] = jasonsFunction(x,y,z);
)nlhs
(Type = int): This paramter represents the number of "left hand side" arguments. So in my example function call, nlhs = 2 (the outputs are z0 and z1).plhs
(Type = array of pointers to mxArrays): This parameter is the actual output arguments. As we will see later, an mxArray is MATLAB's structure for holding data and each element in plhs holds an mxArray of data.nrhs
(Type = int): Similar to nlhs, this paramter holds the number of "right hand side" arguments.prhs
(Type = const array of pointers to mxArrays): This array hold all of the pointers to the mxArrays of input data for instance, prhs[0] holds the mxArray containing x, prhs[1] holds the mxArray containing y, etc).
Getting and Creating Data
The main MATLAB structure used for holding data in MEX-Files is the mxArray. This structure can hold real data, complex data, arrays, matrices, sparse-arrays, strings, and a whole host of other MATLAB data-structures. Using data from some of the basic structures is shown here, but refer to the MATLAB help for using other data structures.
Get that Data
Lets use my example from above (if you forgot:
[z0,z1] = jasonsFunction(x,y,z);
). Assume that x is a 2-D matrix, y is a string, and z is an integer. Here we wills ee how to extract and use these different types of data.We have access to the input paramter x by a pointer held in the array prhs. In C, when referencing an array by index, the variable is automatically dereferenced (ie: you dont need to use a star). For clarity, I will copy the variable x over to an mxArray pointer named xData (This does not need to be done for the code to work).
EXAMPLE 2
//---Inside mexFunction--- //Declarations mxArray *xData; double *xValues; int i,j; int rowLen, colLen; double avg; //Copy input pointer x xData = prhs[0]; //Get matrix x xValues = mxGetPr(xData); rowLen = mxGetN(xData); colLen = mxGetM(xData); //Print the integer avg of each col to matlab console for(i=0;i
The function mxGetPr
is used to get a pointer to the real data xData. This function takes a pointer to an mxArray as the intput paramter, and returns a pointer array of doubles. A similar function mxGetPi
can be used for complex data. mxGetN
and mxGetM
return integers of the lengths of the row and column in the matrix. If this were an array of data, one of these return values would be zero. MATLAB gives the matrix as rows first, then columns (if you were to traverse the matrix linearly) so to jump by position, (x,y) maps to x*colLen+y. MATLAB organizes its arrays this way to reduce cache misses when the row traversal is on the outside loop. It is good to code it this way if you are working for efficiency. printf()
will print out to the MATLAB command prompt.
Getting a string is very similar, but has its own method. The example below shows the procedure for getting a string. Again, I will copy the input to a pointer called yData.
EXAMPLE 3
//---Inside mexFunction--- //Declarations mxArray *yData; int yLength; char *TheString; //Copy input pointer y yData = prhs[1]; //Make "TheString" point to the string yLength = mxGetN(yData)+1; TheString = mxCalloc(yLength, sizeof(char)); //mxCalloc is similar to malloc in C mxGetString(yData,TheString,yLength);
This last example shows how to get a simple integer. This is the method that has always worked for me, but it seems kind of strange so I imagine there is another way to do this.
EXAMPLE 4
//---Inside mexFunction--- //Declarations mxArray *zData; int Num; //Copy input pointer z zData = prhs[2]; //Get the Integer Num = (int)(mxGetScalar(zData)); //print it out on the screen printf("Your favorite integer is: %d",Num);
Three data types have been shown here. There are several others and the MATLAB help as well as the MATLAB example code shows how to use them. Now to export the data....
Returning Data to MATLAB
Assigning return values and data to the left hand side parameters is very similar to getting the data from the last section. The difference here is that memory must be allocated for the data strucure being used on the output. Here is an example of how to return a 2-D matrix. This code will take the input x and return a copy of the matrix to z0 with every point in x multiplied by 2. Note that I am not copying the name of the output mxArray pointer into another variable.
EXAMPLE 5
//---Inside mexFunction--- //Declarations mxArray *xData; double *xValues, *outArray; int i,j; int rowLen, colLen; //Copy input pointer x xData = prhs[0]; //Get matrix x xValues = mxGetPr(xData); rowLen = mxGetN(xData); colLen = mxGetM(xData); //Allocate memory and assign output pointer plhs[0] = mxCreateDoubleMatrix(colLen, rowLen, mxREAL); //mxReal is our data-type //Get a pointer to the data space in our newly allocated memory outArray = mxGetPr(plhs[0]); //Copy matrix while multiplying each point by 2 for(i=0;i
Calling Built-In Functions from a MEX-File
Calling Built-In Functions from a MEX-File
While it may be nice to write functions in C, there are so many useful and fast pre-written functions in MATLAB that it would be a crime if we could not use them. Luckily, The Mathworks (creators of MATLAB) has provided this capability. Built-In functions have a parameter list similar to the mexFunction itself. This example uses the built-in function z = conv(x,y);
EXAMPLE 6
EXAMPLE 6
//---Inside mexFunction--- //Declarations mxArray *result; mxArray *arguments[2]; //Fill in the input parameters with some trash arguments[0] = mxCreateDoubleMatrix(1, 20, mxREAL); arguments[1] = mxCreateDoubleMatrix(1, 10, mxREAL); //In the real world I imagine you would want to actually put //some useful data into the arrays above, but for this example //it doesnt seem neccesary. //Call the Function mexCallMATLAB(1,&result,2,arguments,"conv"); //Now result points to an mxArray and you can extract the data as you please!
Compiling
Compiling
Compiling the MEX-Files is similar to compiling with gcc or any other command line compiler. In the MATLAB command prompt, change your current directory to the location of the MEX source file. Type: mex filename.c
into the MATLAB command window. MATLAB may ask you to choose a compiler. Choose the compiler with MATLAB in its directory path. Your function will be called with the same name as your file. (ex: mex jasonsFunction.c
produces a function that can be called from MATLAB as [z0,z1] = jasonsFunction(x,y,z);
)
After compiling MATLAB produces the actual MEX binary that can be called as a normal MATLAB function. To call this function, you must be in the same directory with the binary. The binary goes by different names depending what system you compiled the source on (ex: Windows=.dll MacOSX=.mexmac Solaris=.mexsol Linux=.mexlx). Your MEX-function will have to be compiled on each type of system that you want to run it on because the binaries are operating system specific.
Other Useful Functions
Other Useful Functions
Here is a nice list of useful functions in the mex library that make life a lot easier. Most of these work in similar fashion to those functions described above. The full list can be found in the MATLAB help documentation with many examples. There are also some example files in the MATLAB extern directory (MATLAB/extern/examples/mx or mex).
mxDuplicateArray
- mexErrMsgTxt
- mxMalloc
- mxRealloc
- mxCreateString
- mxDestroyArray
- mxFree
- mxGetCell
- mxGetData
- and many more...
0 comments:
Post a Comment