[Difficulty printing this document has been reported for the browsers IE6 and IE7. If you encounter this, you can print the document from this PDF version.]
Numerical Recipes code, or for that matter any other C++ code, can easily be invoked from within Matlab, from the console, or from Matlab functions written in m-code. For some tasks, C++ executes hugely faster than Matlab m-code, and you can also access features in Numerical Recipes (or elsewhere) that are not available in Matlab. You can code some parts of your project in m-code and other parts in C++, and control the whole project from the Matlab console or command line.
This document shows how this is done, with examples of two different
coding methodologies: (1) "API", using the Matlab
C API function calls, and (2) "NR3", using the special Numerical
Recipes include file nr3matlab.h. We think that "NR3"
is the best choice (it's simpler to code); but we also show "API"
examples so that you can understand the underlying Matlab interface.
Conventions and Overview
"Hello, world!" Using the Matlab C API
Do Just Once: Introduce Matlab to Your Compiler
The NR3 Coding Method
"Hello, world!" Using nr3matlab.h
Accessing Matlab Vectors with nr3matlab.h
Living Dangerously
Living Safely
Accessing Matlab Scalars with nr3matlab.h
Matrices: "Through the Looking Glass" (TTLG)
Accessing Matlab Matrices with nr3matlab.h
Wrapper Functions That Access Multiple Member Functions in a Class
The API Coding Method
Tips on Matlab C API Programming
Numerical Recipes Using the Matlab C API
Appendix: Using Microsoft Visual Studio
Matlab m-code, or text from the Matlab console is shown on a red background:
C++ code is shown on a green background:
A compiled, executable file that is invoked by a Matlab command is called a "mex file". Mex files are written as source code outside of the Matlab console, in a text editor such as vi or Emacs or the Matlab editor, or in an integrated development environment (IDE) such as Microsoft Visual Studio.
Mex source code files must be compiled and linked. This can be done either from the Matlab console using the command "mex", or else from the IDE. The final step is, if necessary, to move the compiled mex file into your Matlab working directory or path.
A mex file, as one compilation unit, always codes exactly one Matlab-callable function. In fact, the name of the compiled mex-function is the Matlab function name used to access it. (That name typically doesn't even appear in the source code, unless you happen to include it in a comment!)
Of course, within your mex file you can do any number of C++ function calls, memory allocations or deallocations, input-output, and so forth, before returning control (either with or without return values) to the Matlab console or calling m-file. You can also access existing or create new named variables in Matlab's workspace, independent of whether they are input arguments to your mex function.
Here is source code for a mex function that receives an input array of arbitrary size and shape and returns the squares of each of its elements as a row vector. Oh, yes, it also prints "Hello, world!" to the Matlab console.
We compile it from the Matlab console,
An example of using our new mex function is
You might wonder how we got the mex command to compile C++ source, since Matlab comes only with a built-in, rather brain dead, C compiler. The answer is that you need to have a C++ compiler already on your machine and, just once, you need to introduce Matlab to it. For Linux, g++ and Intel C++ are likely compilers; for Windows either Microsoft Visual C++ or Intel C++.
To bind the "mex" command to a compiler, do something like the following:
The above shows a Windows machine with several installed compilers. Your choices may be fewer. Options 1 or 3 above would be good choices. Option 2, the brain-dead C compiler, would not be.
The NR3 coding method uses wrapper functions that are in
the include file nr3matlab.h instead
of the Matlab C API. Of course, you can also use any
of the API functions directly. But you should rarely or never need to.
Mex source files in the NR3 coding method always have exactly the framework
The void mexFunction(...) line is somewhat equivalent to
the int main(...) in ordinary C++ programming. (You
don't include a main routine in mex files.)
Within your mex code, you are given the integer number of arguments,
nrhs, and the expected number of returned values
nlhs. Both arguments and return values may
of course be arrays. Below, we'll see how to use the
input arguments plhs and prhs
with the NR3 coding method.
Although the order of presentation might at first seem odd, we'll discuss vectors, then scalars, and finally matrices. But, before any of these, we must of course repeat the "Hello, world!" example, now in NR3 coding style:
Using the NR3 coding method, our "Hello, world!" mex function is rather more readable than before.
Execution is no different from before.
The include file nr3matlab.h is mostly the same
as the standard NR3 include file nr3.h. What it
adds are some new vector constructors and a new
vector member function. These make it easy to
interact with Matlab vectors in a natural way, without
needing to use the API mx-functions. (That is, natural
for C++ programmers who have a copy of Numerical Recipes!)
For reference, the additions to the templated
class NRvector are:
You don't really have to understand the above declarations, or their definitions, in detail. Here are some usage examples:
See, no mx-functions! Except, of course, mexFunction
itself, which is always required.
Although the above example shows only VecDoub exemplars,
everything would work fine for other types of vectors, e.g., VecInt.
The constructors check for type consistency
as necessary, and report an error if you have done something
type-inconsistent. Let's see it work:
The nr3matlab.h vector constructors can access any
numerical Matlab array, flattening it to a vector in the Matlab
storage order ("by columns" or "Fortran-like" or "reverse of
odometer"). So, for example,
Notice that the "dangerous" operations, because they write directly into Matlab's workspace, don't flatten the matrices to vectors, since the matrices stay in Matlab space.
Officially, we have to say, "don't do it!". But since the reason you are progamming C++ within Matlab is probably for performance on big data sets, you will probably want to use the operations that we label above as "dangerous". We use them all the time.
What is dangerous about these operations is not that they will crash Matlab or void your warranty (if there were one, always doubtful for software). The danger is that they can have unintended computational side-effects. If you understand these, you can manage them; but if you don't, you might be rather surprised:
Knowing that bb was going to be modified
by NRvectorDemo, you carefully saved a copy
bbsave. But look: it got modified too.
The reason is that Matlab's clever memory management
uses a "copy on modify" strategy. Had you modified bb
inside Matlab, it would have copied bbsave's values
at that point. But since we modified it with a "dangerous"
method, undetectable by Matlab, the saved copy never got made.
Moral: If you are going to use nr3matlab.h's ability
to modify values directly in Matlab space, be sure that there
are no exact copies of the variable that you care about.
If necessary, you can enforce uniqueness by trickery, such as
but this should almost never be necessary if you just keep in mind the copy history of your large-data variables.
So, shouldn't this scare you away from living dangerously? Maybe.
But suppose you have a Matlab data vector of
length 108, and you intend to apply a series of C++ mex
functions to some specific components of the vector. You can
read those components using non-dangerous
nr3matlab.h methods. But the only non-dangerous way to
write them is by the .put() method, which copies
back the whole vector. If that is just too slow, then the "dangerous"
operations are just what you need.
If you worry that you might accidentally write into Matlab
space, you should declare vectors derived from
rhs arguments or Matlab named variables with const.
Then, the compiler will catch any such accidents. Changed lines
from the example above are:
If you later decide that you do want to write into Matlab space after all, you can do something like this:
Turn now to Matlab scalars.
Since scalars like double and int
are fundamental types, we can't overload
functionality into their constructors, as we did for vectors.
Instead,
within nr3matlab.h several overloaded versions of
a templated function mxScalar are defined. (Note that, despite
the naming convention, this is a Numerical Recipes, not a MathWorks,
function.) These functions let you grab scalar values, either
from your mex function's arguments, or from variables in the
Matlab workspace. They also let you bind a C++ variable to
any of your function's return values, and copy scalar values
into named variables (existing or new) in Matlab's workspace.
For reference, the functions are declared as follows:
Easier to understand is sample code. (Note that we are now
programming in NR3 style, using typedef'd types like Doub.
You don't have to do this if you don't want to.)
The action of this function is to return the square of its first
argument and set the named variable dd to be the square
of the named variable cc. It then does two "dangerous"
operations: It changes the value of its second right-hand-side
argument to its square, and it overwrites a non-const reference to the named
variable ff with its square. Let's watch it go:
You can verify that the "after" values are what we expect.
Although the above example shows only Doub scalars,
everything would work fine for other types (e.g., Int).
The mxScalar fuctions check for type consistency
as necessary, and report an error if you have done something
type-inconsistent.
Notice that the mxScalar fuctions
are templated, and always require an explicit template argument
like mxScalar<double>() or mxScalar<int>().
This is so that type checking against Matlab's type can be made
automatic, with an error thrown if you try to do something bad.
Also note that most Matlab scalars are double, even
things like array sizes that are more logically an integer. So
you will often find yourself importing arguments like this:
Matrices are handled pretty much like vectors, above, except
for one fly in the ointment, the fact that Matlab and C++
store the elements of a matrix in different orders.
You must understand this before using
nr3matlab.h with NRmatrix data types,
or you will be rather unhappy: your matrices will sometimes be the
transpose of what you expected!
NRmatrix data types include NR3 types
like MatDoub, MatInt, etc.
The goal is performance: We want to be able to work with potentially large amounts of data from both the Matlab side and the Numerical Recipes side of the mex interface. What we must avoid is unnecessary copying back and forth, not only because of the actual copying, but also because of the overhead involved in rapidly allocating and deallocating large chunks of memory (thus possibly driving Matlab's memory manager into poor performance).
Therefore, we want to point directly into Matlab's memory, both to read data and also (with some restrictions) to write it. For scalar values and vectors, we saw that this posed no special problems except understanding the implications of "dangerous" operations and avoiding them, or not, according to your taste. Matrices have the additional problem of storage order: Matlab is hard-wired to store by columns ("Fortran order" or "reverse of odometer"), while C++ is hard-wired to store by rows ("C order" or "odometer order").
We adopt a "Through the Looking Glass" (TTLG) approach: In our interface, when a Matlab matrix crosses the interface into C++, what appears on the other side as its transpose. When it (or any other C++ matrix) is sent back across the interface to Matlab, what appears is also the transpose of what was sent. So, for example, a matrix that makes a round trip into C++ and back again (without being modified by C++ code) is unchanged.
The good news about the TLGC approach is that it makes for a very clean
and efficient interface. The bad news is that you have to
remember that you always receive the transpose of what was sent. Usually
you can just code for this on-the-fly: Where you might have
written mymatrix[i][j], you instead write
mymatrix[j][i], and so forth. In many cases,
such as doing something in parallel to all the elements of a matrix,
there is nothing to remember at all. Occasionally, when you absolutely need
to process an un-transposed matrix, you have to take an explicit
transpose. This of course will use memory allocation and add overhead.
It is important to understand that each side of the TTLG interface
is self consistent according to its own usual conventions, both
as to size and as to subscript numbering (1-based in Matlab vs.
0-based in C++).
So, if mymatrix is 3x5 in Matlab (3 rows, 5 columns), and thus
5x3 in C++ (5 rows, 3 columns), then the following quantities are
numerically equal:
size(mymatrix,1) = 3 = mymatrix.ncols()size(mymatrix,2) = 5 = mymatrix.nrows()mymatrix(1,1) = mymatrix[0][0]mymatrix(2,4) = mymatrix[3][1]
For reference, the additions to the templated
class NRmatrix are:
Easier to understand are some usage examples:
From the Matlab side, we can use the mex function NRmatrixDemo like this.
Notice that the modified element is b[0][1] on the
C++ side, but b(2,1) on the Matlab side, because
of the TTLG approach.
If you want a single mex file to perform multiple functions (for example, call different member functions within a single class), you'll need to figure out on the C++ side what is intended from the number and type of right-hand side arguments. You can also include arguments of character type that can function as keywords.
For example, a simple wrapper for the Numerical Recipes class
Gaumixmod (Gaussian mixture model)
might have these possible calls on the Matlab side:
The corresponding C++ looks like this. Note the use of the
functions mxT() and mxT<>()
to test the type of Matlab arguments. These functions are
in nr3matlab.h.
Note that, once instantiated, the pointer *gmm is
persistent between calls until we explicitly delete it. You'd need
a more complicated scheme to instantiate more than one Gaumixmod
object at a time.
You need to read the following sections only if you want to go beyond
the capabilities provided by nr3matlab.h and use
Matlab C API calls directly.
Mex file programming using the C API interface is well documented on the MathWorks web site. A good starting page is the chapter on external interfaces, as well as the C API Reference page. Nevertheless, we will make a few additional points here.
The void mexFunction(...) line is somewhat equivalent to
the int main(...) in ordinary C++ programming. (You
don't include a main routine in mex files.)
nrhs, the expected number of returned values
nlhs, which may of course be arrays, an array of
pointers to the input structures (mxArrays), and
an array of pointers that you populate with
output mxArrays, as shown in the example.
indata). The
ordering is always by columns, not rows, or, more generally,
with the last subscript changing least rapidly ("reverse of odometer"
or "Fortran order"). It is easy to find out Matlab's view of the
internal matrix arrangement by API calls like mxGetM,
mxGetN, mxGetNumberOfDimensions,
mxGetDimensions, and a few others. But, once you
do this, it is up to you to locate by subscript(s) any desired elements.
(This is basically what the nr3matlab interface is
designed to make easier.) Matlab's Fortran storage ordering has other
implications that are discussed in the section
Matrices: "Through the
Looking Glass", above.
mxGetData function returns a void pointer to
the data. It is up to you to cast it to the intended C++
type. Above, we trusted the user to send us double
data, which is Matlab's default type (even for things that you
might otherwise expect to be integers). That is, of course, bad
programming. We should have used API functions like mxIsDouble
or mxGetClassID to get Matlab's opinion as to the
data type, and then aborted with mexErrMsgTxt if
it is not the expected enum value mxDOUBLE_CLASS.
If you plan to use the API interface, you should peruse the
file matrix.h located in the /extern/include directory
of your Matlab installation. Among other things, this file
defines the class names like mxDOUBLE_CLASS.
Although we prefer to use the NR3 coding method, above, you
can perfectly well use Numerical Recipes Third Edition (NR3)
code, and the standard nr3.h include file,
with the Matlab C API interface.
For example, here is a mex file that makes NR3's generalized Fermi-Dirac integral routine available to Matlab. (The NR3 routine does a fancy quadrature, using the DE rule.)
Compile this with the mex command, then put it in your Matlab working directory.
Now you can also do powerful Matlab things, like making a contour plot of the logarithm of the function.
(see Matlab help for "contour" to understand this) which produces

Because this example passes and returns scalars only, the file
fermidirac.cpp would not look too different in the NR3
coding method: mxScalar would replace
mxGetScalar, throw would replace
mexErrMsgTxt, and mxCreateDoubleScalar would
disappear (since f could be declared directly as the
return value plhs[0]).
In all sections above we've done the compilation and linking
from the Matlab console, using the mex command.
We saw in the section
Do Just Once: Introduce Matlab to Your Compiler
that we could cause the mex command to use our
favorite compiler. But we were not getting the convenience of
compiling within an integrated development environment (IDE)
such as Microsoft Visual Studio. This section explains how
to do this for Matlab 7.1+ and Visual Studio 2005. Other
versions should be similar.
We follow the useful article by "abn9c". We suppose that your function is called MyFunc (make the obvious changes below for whatever it is actually named).
Follow these steps:
and add it to the Solution. You can create it with the menu File/New/File..., choosing "Header File .h" type. But after you enter the above text, save the file as MyFunc.def, not MyFunc.h. Add it to the Solution via menu Project/Add Existing Item...
Now go to the menu Project/MyFunc Properties for the following steps:
You can now "OK" out of "MyFunc Property Pages".
before the linker can overwrite a new file, or before your new executable is recognized by Matlab.
Microsoft Visual Studio doesn't make it easy to copy all the above settings from one project to another. There are various commercial tools for this, so that you don't have to keep going through all the above steps for each new mex function that you write. (We use one called CopyWiz.)