1615 Is there a Tutorial for Creating MEX-files with Emphasis on C MEX-files?

Revision 1.0

Introduction

This tutorial provides a general overview of MEX-files and a detailed explanation of the external interface functions that allow you to interface C or Fortran subroutines to MATLAB. It includes C MEX-file code examples that demonstrate the use of the external interface functions.

MEX stands for MATLAB Executable. MEX-files are dynamically linked subroutines produced from C or Fortran source code that, when compiled, can be run from within MATLAB in the same way as MATLAB M-files or built-in functions. The external interface functions provide functionality to transfer data between MEX-files and MATLAB, and the ability to call MATLAB functions from C or Fortran code.

MATLAB for Windows supports two formats for MEX-files: REX (Relocatable Executable) format and DLL (Dynamic Link Library) format.

The REX format uses 32-bit code, thus yielding performance comparable to MATLAB's built-in functions. REX-format MEX-files are recommended for numerically intensive applications.

The DLL format (which is 16-bit code) yields slower performance and necessitates the use of huge pointers to deal with matrices larger then 64k. The advantages of using a DLL format is that it allows you to access the functions in the Windows environment (i.e., to create custom user interfaces for your applications).

Why Use MEX-files?

There are several situations where you might want to use a MEX-file:

Components of MEX-files

There are a number of issues that need to be understood in order to write your own C MEX-files.


Example of the World's Smallest MEX-file

mexPrintf(format,...) is, for the most part, just like C's printf function. See the FAQ at the end of this document for exceptions. format is a format-specifier string, which can be followed by some arguments. mexPrintf uses the format-specifier string to print the arguments (or the contents of the arguments, if they are variables) to the MATLAB command window. For example,


would print


MATLAB Variables (Matrices)

Before we can discuss the inputs and outputs of MEX-files, we need to understand what a MATLAB variable is.

Each MATLAB variable is a matrix (even strings and scalars are considered to be matrices). A matrix is the C-language definition of a MATLAB variable. It is a structure containing the following information:

For a full (nonsparse) matrix, pr and pi are one-dimensional arrays of doubles. The data in the matrix is stored in these arrays columnwise, the same way that Fortran stores its two-dimensional arrays (this is because MATLAB was originally written in Fortran). For example,


would be stored in the matrix (or C structure) as


Note that if a matrix is purely real (all imaginary elements are zero), then the pi pointer equals NULL.

The structure of sparse matrices is not dealt with in this tutorial. However, it's described in the Sparse Matrices section of this document.

Inputs and Outputs of MEX-files

Inputs

Outputs

The variables nlhs and nrhs specify the number of left-hand and right-hand side arguments that are used when the MEX-file is called. They are analogous to the MATLAB variables nargout and nargin, respectively. For example, if the MEX-file was called in MATLAB using


then nlhs equals 2 (for a and b), and nrhs equals 3 (for d, e, and f).

prhs is an array of pointers to the input matrices. Thus, in the above example, plhs[0] is a pointer to the matrix d, and prhs[1] is a pointer to the matrix e. plhs is an uninitialized array. If plhs is greater than zero, then the MEX-file should fill the plhs array with pointers to matrices containing valid data, or generate an error message stating that too many outputs were requested.

The MEX External Interface provides several functions that allow you to determine various states of a matrix. These functions are used to check the input to the MEX-file to make sure it's what's expected. The functions that have the prefix mxIs are:

i = mxIsComplex(mp)                   i = 1 if pi<>NULL, 0 otherwise        
i = mxIsFull(mp)                      i = 1 if matrix is Full, 0 if         
                                      matrix is sparse                      
i = mxIsSparse(mp)                    i = 1 if matrix is Sparse, 0 if       
                                      matrix is Full                        
i = mxIsNumeric(mp)                   i = 1 if matrix is numeric, 0 if      
                                      matrix is a string                    
i = mxIsString(mp)                    i = 1 if matrix is a string, 0 if     
                                      matrix is numeric                     
i = mxIsDouble(mp)                    i = This is for future                
                                      compatibility, in case matrices       
                                      ever contain non-double elements.     

In order to prevent passing inputs that are the incorrect type, use the mxIs* functions extensively at the beginning of your MEX-file. For example, suppose prhs[0] is supposed to be a regular, full, real-valued matrix. To prevent passing your function a sparse matrix, a string matrix, or a complex matrix, use code similar to the following:


Putting these checks in prevents your MEX-file from crashing, for no apparent reason, when you accidentally pass it the wrong type of data.

Example: MEX-file Checking Inputs and Outputs

The function mexErrMsgTxt works like the MATLAB function error. When called, it exits the MEX-file, and reports an error message specified in the input string.

The MEX-file example first checks to make sure that the function was called correctly, with the correct number of inputs and outputs. It verifies that the input is a scalar. Then, using the mxIs* functions, it verifies that the input is a full nonsparse matrix. Finally, it gets the pointer to the real part of the output matrix and fills in its first element with the function's output.

Allocating Matrix Structures

The MEX External Interface provides three functions to create matrices to be passed to MATLAB.

To clear the matrix structure defined by the above functions use:


Creating Matrices:

The following variable declarations will be used:

stris of type char *
mpis of type Matrix *
xis of type double
xpis of type double *
iis of type int
ipis of type int *
nzmaxis of type int

mp=mxCreateFull(m,n,complex_flag) allocates memory for a new full m by n matrix. complex_flag is REAL for a real matrix, and COMPLEX for an imaginary/complex matrix.

mp=mxCreateSparse(m,n,nzmax,complex_flag) allocates memory for a new sparse m by n matrix. Nzmax is the maximum number of nonzero elements in the sparse matrix. complex_flag is as above.

mp=mxCreateString(str) allocates a string matrix and copies the contents of str into it.

mxFreeMatrix(mp) frees (destroys) a full or sparse matrix.

Accessing String and Scalar Matrices:

errcode=mxGetString(mp,str,strlen) copies up to strlen characters out of the matrix mp into the character buffer pointed to by str. str must be preallocated either statically or via mxCalloc. Errcode is 0 for success, 1 if mp is not a string matrix or length of mp is greater than strlen.

x=mxGetScalar(mp) returns the (1,1) element (of the MATLAB matrix) of the matrix mp.

Allocating/Deallocating Memory:

voidptr=mxCalloc(n,size) - is similar to the C calloc function, but allocates memory from the MATLAB heap. n is the number of elements to allocate; size is the size of each element.

mxFree(voidptr) - is similar to the C free function. It frees/deallocates memory allocated with mxCalloc.

Accessing Individual Members of Matrix Structures

These functions provide access to the individual matrix structure members.
Matrix memberTypeTo read from MatrixTo write to Matrix
namechar *str = mxGetName(mp)mxSetName(mp,str)
minti = mxGetM(mp)mxSetM(mp,i)
ninti = mxGetN(mp)mxSetN(mp,i)
prdouble *xp = mxGetPr(mp)mxSetPr(mp,xp)
pidouble *xp = mxGetPi(mp)mxSetPi(mp,xp)
irint *ip = mxGetIr(mp)mxSetIr(mp,ip)
jcint *ip = mxGetJc(mp)mxSetJc(mp,ip)
nzmaxintI = mxGetNzmax(mp)mxSetNzmax(mp,i)

Where mp represents type Matrix *

With the matrix access routines provided by The MathWorks, it is not necessary to know the actual structure of a matrix. The matrix access functions, which all begin with the sentinel characters mx, provide access to the matrix, which allows for future changes in the structure of the matrix without having to rewrite MEX-code.

Note that the mxSet* commands are "dumb." That is, if you set one part of the matrix using an mxSet* function, then it is up to you to make sure the rest of the matrix contents are consistent. For example, if you set m and n to be 3 and 2, it is up to you to make sure pr and pi are six element arrays of doubles.

Example: MEX-file Accepts One Input and Returns One Output

Registering an Exit Function

Another advantage of MEX-files is that they can have static memory. This means that variables inside the MEX-file that are declared static retain their values from call to call of the MEX-file. Any initialization of these variables occurs when the function is called for the first time, i.e. when the function is loaded into memory.

Certain events can cause MATLAB to remove the MEX-file from memory. Some examples of these events are:

When MATLAB removes a MEX-file that contains a static variable from memory, the static variable is lost. The next time the MEX-file is called, it loads into memory again, and all static variables are reinitialized to their original value. Therefore, there needs to be a way to warn you and the MEX-files that it is being unloaded, so that it can clean up any data structures it maintains, and save any important data it has. This is accomplished with an exit function.

An exit function is called by MATLAB just before it unloads its corresponding MEX-file. Each MEX-file is allowed to have its own exit function, but no MEX-file can have more than one exit function. The MEX-file registers its exit function by calling the mexAtExit function. The exit function must return a void, and cannot accept any input arguments.

This example shows an exit function, as well as the corresponding call to mexAtExit, registering the exit function:


Data Transfer: MEX-files <==> MATLAB

These functions allow you to pass matrices to and get matrices from MATLAB.

Get Matrices from MATLAB                 Put Matrices in MATLAB                   
mexGetMatrix *                           mexPutMatrix *                           
mexGetFull *                             mexPutFull **                            
mexGetMatrixPtr*                                                                  


Passing Matrices Between MEX-files and MATLAB

Usually, matrices are passed to MATLAB via the right-hand side (rhs) and the left-hand side (lhs) method. This means that variables are passed into and out of a function by being included as arguments to the function. Sometimes, there are cases in which you may need to violate this standard. Some examples are:

Unlike function M-files, MEX functions have the unique ability to get matrices from the workspace of the calling function, without having the matrix passed in via the prhs structure. The "calling function" is the M-file function from which the MEX-file is called. When a MEX-file is called from an M-file script or the command line, the calling function's workspace is the main MATLAB workspace. For example, assume you call the following function:


Even though themexfun is only passed the variable x, it can still gain access to the variable y. The following code fragment shows one way this can be done from inside the MEX-file (assuming mp is a Matrix *):


When this code is executed, a copy of the variable y is made, and mp is assigned to point to it. Because a copy of the variable is made, you must remember to free mp with mxFreeMatrix when you are done with it.

The following examples describe the three mexGet* functions that can access a matrix in more detail. The examples use these variable declarations:


  1. Example of using mexGetMatrix()

    mp=mexGetMatrix(name) - Make a copy of the matrix whose name is specified by name from the calling function's workspace. Return a pointer to the copy, or NULL if the matrix doesn't exist. Remember to free mp with mxFreeMatrix.


  2. Example of using mexGetFull()

    errcode=mexGetFull(name,&m,&n,&pr,&pi) - Similar to mexGetMatrix, but instead of returning a matrix pointer, the various elements of the matrix are copied directly into m, n, pr, and pi. Note that you do not need to allocate memory for pr and pi, because mexGetFull does this for you. But, you do need to free pr and pi with mxFree when you are done with them. As its name implies, this function can only be used with full matrices, not sparse ones. Errcode is 0 if successful, 1 if the matrix doesn't exist.


  3. Example of using mexGetMatrixPtr()


MEX-files can also place variables into the calling function's workspace. When doing this, if a variable with the same name already exists in the calling function's it is deleted and replaced with the new variable. Otherwise, the variable is simply placed into the workspace. For example, suppose this code appeared in the MEX-file themexfun:


Assume that before running themexfun, there were no variables in the current workspace. After running themexfun, there would be a variable named A in the current workspace, containing the string Hi there.

The following describes the two functions that allow for putting matrices into a workspace. The same declarations as above are used here:

errcode=mexPutMatrix(mp) - Put a copy of the matrix pointed to by mp into the calling function's workspace. If a variable with the same name already exists there, it is replaced. errcode is 0 for success and 1 if an error occurred.

errcode=mexPutFull(name,m,n,pr,pi) - Similar to mexPutMatrix, but rather than taking a pointer to a matrix as input, the various parts of a full matrix are passed to it instead. This function allocates a matrix of size m by n, copies the data from pr and pi to it, and gives it the name specified by name. It then passes the matrix to the calling function's workspace in the same way as mexPutMatrix. As with mexPutMatrix, errcode is 0 for success and 1 if an error occurred.

In general, use caution when using any of the mexGet* or mexPut* functions. These functions, especially the mexPut* functions, are likely to have strange side effects, which at best create strange variables in your workspace, and at worst write over your data without you knowing about it. These effects are documented in the function's on-line help.

Calling MATLAB Functions From MEX-files

The next two functions allow you to call other MATLAB functions.


Calling Another Function from a MEX-file Using mexEvalString

errcode=mexEvalString(str) - Similar to MATLAB's eval function, this function evaluates its string input in the calling function's workspace, in the same manner as if it had been entered at the MATLAB command line. For example,


would generate a plot of 1 to 10 in the current figure window. Note that since the command is evaluated in the calling function's workspace, the variable p is stored in the calling function's workspace. Thus, if the MEX-file were to be called from within an M-file function, p would be stored in that function's workspace, not the main workspace.

Although mexEvalString is easy to code, the string passed to mexEvalString is evaluated by MATLAB, therefore, the MATLAB parser has to be called. Calling another MEX-file via the mexEvalString is not very efficient since the MATLAB parser is called. Also, all variables created by the mexEvalString command are stored in the workspace of the function text called by the MEX-file, which may need to be retrieved with the mexGet* functions. A more efficient way to accomplish the same goal is to use the mexCallMATLAB function (assuming you're calling a function and not a script).

Calling Another Function from a MEX-file Using mexCallMATLAB

Other MATLAB functions, including built-in functions, MEX-file and M-file functions, (not M-file scripts) can be called from within a MEX-file using the mexCallMATLAB function.

This function accepts five inputs. The first four are structured exactly the same as the inputs to mexFunction which are nlhs,plhs,nrhs, and prhs, are int's, and plhs and prhs are pointers to arrays of matrices. You set up nrhs, prhs, and nlhs to contain what you want passed to the MATLAB function that you are calling. The function returns any output data in plhs. Thus, it is as if your MEX-file is acting as the MATLAB parser, arranging the data in the correct data structure and passing it to the function. The fifth argument is a character string containing the name of the MATLAB function to be called. The following is an example of this that calculates the determinant of a matrix and prints it out. The example assumes the matrix pointer mp has already been initialized to contain valid data:


There are three things to note here.

  1. Any variable created by the MATLAB function and returned (by mexCallMATLAB) in the plhs data structure must be freed by your MEX-file when you are done with it.

  2. Even if a function is called with nlhs equal to zero (no output arguments requested), it can still return up to one matrix. This matrix is assigned to the built-in variable ans if the function is called from the command line. Therefore, even if you set nlhs to zero when calling mexCallMATLAB, you should still make sure that plhs contains space for at least one output matrix, and you should never pass NULL for plhs. *plhs is an array of matrix pointers. If nlhs == 0 this means plhs[0] == NULL and not plhs == NULL. Therefore, the correct syntax to assign plhs when there are no output arguments is:

  3. You can access MATLAB's operators, such as * (multiplication) and / (division), by specifying the operator in string form as the fifth input to mexCallMATLAB.

The following is a list of all the valid operators that can be used with the mexCallMATLAB function:

=|&
:>>=
<<===
~=-~
+*/
\ .*./
.\ ^.^
' '

Thus, to add two matrices together, you could make the following call (assuming prhs already contains the two matrices):


Ordinarily, if an error occurs in the function call made by mexCallMATLAB, MATLAB prints the appropriate error message and returns to the command prompt. However, by using the mexSetTrapFlag function, you can change this behavior. Calling mexSetTrapFlag(1) will set the trap flag so that if an error occurs, mexCallMATLAB will return control to the MEX-file. mexCallMATLAB will then return an integer error code of zero if the function call was successful, and nonzero if an error occurred. Calling mexSetTrapFlag(0) returns mexCallMATLAB to its default behavior.

Sparse Matrices

The best way to explain how sparse matrices are stored in matrix structures is through an example.

Given a 4-by-4 full matrix A:


and converting it to a sparse matrix results in the following sparse matrix characteristics:


This sparse matrix will be stored in memory in the following manner:

pr is a pointer of type double

ir and jc are arrays of type integers

pr --->5.09.07.08.01.06.0pr has nzmax
elements;contains
doubles

ir --->132302ir has nzmax
elements; contains
integers

jc --->00246jc has n+1 elements;
n=number of columns;
contains integers

Note: Indexing off of 0 (not 1) will be used to reference elements of the pr, ir, and jc arrays and also of the matrix A.

Each element in the ir array indicates in which row (of the A matrix) the corresponding value (using same index as in ir) in pr is located.

For example, the first element (the zero'th index) in the ir array is 1, thus the corresponding element (zero'th index of pr) in pr is in row 1 of array A (indexing A off of zero). Here's a table of the first few elements:

matrix
property
indexvalueExplanation
ir
pr
0
0
1
5.0
therefore, in row 1 of A you'll find 5.0
ir
pr
1
1
3
9.0
therefore, in row 3 of A you'll find 9.0
ir
pr
2
2
2
7.0
therefore, in row 2 of A you'll find 7.0

The jc array is a little more tricky. If you traverse the A matrix (indexing off of 0) in a column order and you only count the nonzero elements, it results in the following vector of nonzero elements:

nonzero values:597816
-----------------> 012345
(indexing this vector off of 0)

By looking back at the A matrix you see that the values 5, 7 and 1 are the first nonzero occurrences in each row. These values correspond to the indices 0, 2, and 4 of the vector created of all the nonzero elements of the A matrix.

The jc array is made up of indices of the first nonzero element for each column of the A matrix. jc arrray always starts with 0; whether it is because the 1st column of A contains all zeros or because the 1st non-zero element of the 1st column of A is in the 0th index of pr. The second entry of the jc array is the number of non-zero elements prior to the second column of the matrix A and the third and the fourth entries are the number of non-zero elements prior to the third and fourth columns, respectively. This paradigm can be followed for larger sparse matrices. The final value of the jc array is the actual number of the non-zero elements in the matrix; thus, for matrix A, it is 6. Therefore, the jc array is:

jc --->00246

Summary of Terms and Acronyms

Calling Function's
Workspace The workspace of the function that calls the MEX-file.
If the MEX-file is called from a script or from the MATLAB command line, this is the main MATLAB workspace
Exit functionFunction called before a MEX-file is deallocated.
MEXabbreviation for MATLAB Executable. See MEX-file.
MEX-file A file containing a compiled MEX-file or C Fortran code function.
When it is compiled, it can be run from within
MATLAB in the same way as an M-file function.
Matrix The C-language representation of a MATLAB variable.
Matrix Access
Routines
functions that provide access to the parts of a matrix
structure
Trap Flag If this flag is true, mexCallMATLAB returns control to the
MEX-file after an error. If false, mexCallMATLAB returns
to the MATLAB command prompt

mexFunction Input and Output Argument List
nlhsNumber of left-hand side (output) arguments from a MEX-file.
nrhsNumber of right-hand side (input) arguments to a MEX-file.
plhsArray of pointers to left-hand side arguments for a MEX-file.
prhsArray of pointers to right-hand side arguments for a MEX-file.

List of External Interface functions

mex* Routine
mexAtExitFunction to register a MEX-file's exit function.
mexCallMATLABFunction to call a MATLAB function from within a
MEX-file.
mexErrMsgTxtFunction that reports an error in a MEX-file.
mexEvalStringFunction that evaluates a string using the MATLAB
parser.
mexFunctionFunction that is called first when a MEX-file is
called from MATLAB.
mexGetFullFunction to get the information in a matrix from the calling function's workspace.
mexGetMatrixFunction to get a matrix from the calling
function's workspace.
mexGetMatrixPtrFunction to get a pointer to a matrix in the
calling function's workspace.
mexPrintfFunction to print to the MATLAB command window.
mexPutFullFunction to put matrix information into a matrix,
which is then placed into the calling function's
workspace.
mexPutMatrixFunction to put a matrix into the calling
function's workspace.
mexSetTrapFlagFunction to set mexCallMATLAB's trap flag.

mx* Routines
mxCallocFunction to allocate a block of memory dynamically.
mxCreateFullFunction to allocate a new full matrix dynamically.
mxCreateSparseFunction to allocate a new sparse matrix dynamically.
mxCreateStringFunction that allocates a new string matrix and
copies a C string into it.
mxFreeFunction to free memory allocated with mxCalloc.
mxFreeMatrixFunction to free a dynamically allocated matrix.
mxGetIrFunction to get the pointer to the ir vector of a
sparse matrix.
mxGetJcFunction to get the pointer to the jc vector of a
sparse matrix.
mxGetFunction to get the number of rows of a matrix.
mxGetNFunction to get the number of columns of a matrix.
mxGetNameFunction to get the name of a matrix.
mxGetNzmaxFunction to get the maximum number of nonzero
elements in a sparse matrix.
mxGetPiFunction to get the pointer to the imaginary part of
a matrix.
mxGetPrFunction to get the pointer to the real part of a
matrix.
mxGetScalarFunction which returns the (1,1) element of a matrix.
mxGetStringFunction which copies a string matrix into a C string.
mxIsComplexFunction which returns true for complex matrices.
mxIsDoubleFunction that returns true if a matrix contains
double precision elements.
mxIsFullFunction that returns true for full (nonsparse)
matrices.
mxIsNumericFunction that returns true for numeric matrices.
mxIsSparseFunction that returns true for sparse matrices.
mxIsStringFunction that returns true for string matrices.
mxSetIrFunction to set the pointer to the ir vector of a
sparse matrix.
mxSetJcFunction to set the pointer to the jc vector of a
sparse matrix.
mxSetMFunction to set the number of rows of a matrix.
mxSetNFunction to set the number of columns of a matrix.
mxSetNameFunction to set the name of a matrix.
mxSetNzmaxFunction to set the maximum number of nonzero
elements in sparse matrix.
mxSetPiFunction to set the pointer to the imaginary part of
a matrix.
mxSetPrFunction to set the pointer to the real part of a
matrix.

Frequently Asked Questions (FAQ) about MEX-files

Question

What do the following error messages mean (compiling with Metaware High C 3.01)?


Answer

Errors such as the ones above, that have to do with entry points and initialization, often occur due to slight differences between the compiler being used and the compilers that are officially supported by The MathWorks. Despite the error message, many times a working MEX-file is created. If a MEX-file is created after getting these error messages, try running the MEX-file to see if it works correctly. If it does, ignore the error message.

Question

How can I access a global variable from inside a MEX-file?

Answer

In MATLAB 4.2, there is a new mex* function called mexGetGlobal that will access global variables for you. It uses the same calling syntax as mexGetMatrixPtr.

Question

When creating DLL MEX-files I either get unresolved reference errors for matOpen, matClose, matGetMatrix, and matGetDir functions, or unresolved external sscanf. Why?

Answer

MEX-files created by Microsoft's Visual C++ and Borland's C/C++ are implemented as (16-bit) DLL functions. Microsoft and Borland do not support the sscanf function within DLL functions. Since the libmat.lib library that supplies the mat* functions requires the sscanf function, there is no way to call mat* functions from a DLL MEX-file.

Question

Printing with the %f, %g, and %e printf format specifiers within DLL functions do not appear to work. Why?

Answer

Microsoft and Borland do not support the %f, %g, and %e format specifiers in DLL functions.


(c) Copyright 1996 by The MathWorks, Inc.