Using C/C++ under Matlab (Part 2)

Author

Benoit Guilleminot

Keywords

Matlab, C, C++, Mex Files

Review Status

Draft


Creating a MEX project under Visual C++ Express 2008

Matlab is provided with a default compiler that you can invoke with the command “mex”. It is good enough for simple projects where extra configuration of an external compiler is not really needed. However for more complex projects, debugger or dedicated IDE (with completion :-) and linker optimization for instance) are very useful. The configuration of Visual C++ Express Edition 2008 (free) is explained below.

Compiled functions under Matlab are in fact system libraries (dll files under Windows) renamed with a .mexw32 (.mexw64 if you work on a 64 bits machine). Matlab will run any file with such an extension as a compiled function.

As with any m-file the function name is determined according to file name. If your file is called foo.mexw32, then the function will be executed by simply running the command foo.

So let’s start with a simple example that can serve as a template.

As a simple example we want to create a compiled function that sets all the negative elements of a vector to zero (see Enrico’s example on the Wiki Replacing negative elements of a vector by 0)

1. Creation of an empty project

  • Create a simple project under VC++ (File / New Project), call it as you wish.
Img1
  • On the left hand side, click on “Application Settings” (or equivalently click on the “Next” button) and make sure that you select “DLL” and tick “Empty project”.
Img2
  • Creation of the definition file

In order to run your code Matlab needs to know where the “entry point” is. In any M-files the execution starts at the first line of the first function found in the M-file. Other functions may exist in the file but they are executed only when you call them.

In the case of compiled files the same principles apply. Some functions are created to be called from outside, others are just useful inside your own code.

In the case of MEX files, Matlab will always try to run a function called “mexFunction”. Therefore we need to tell the compiler that this function must be accessible from outside. You can do as follows :

* Create a new empty file with the extension “.def”. In this case I have added the file “keepPos.def”.

(An easy way to do that is just to create a simple header file and to rename it “Right click on the project name / Add / New Item / Header File à and update the name)

* Move the file at the root of the project.

This file is called a definition file. As explained briefly before it is used by the compiler/linker to know what functions will be accessible from outside.

Here is the syntax to follow:

LIBRARY KEEPPOS
EXPORTS mexFunction
Img3

2. Configuration of Compiler

Now we need to define some important properties of the project in order to ensure that the output file is fully compatible with Matlab.

Open project properties (Right click on the project name / Properties).

Start with the “Configuration Properties / C/C++” tab

* Under “General / Additional Include Directories ”add Matlab external include directory :

Img4

* Then add the following string “MATLAB_MEX_FILE” to the list of Preprocessor definitions

Img5

*Make sure that under “Advanded”, the convention “_cdecl” is chosen.

3. Configuration of Linker

Now look at the “Configuration Properties / Linker” properties

a. Under “General”, define the name of the “Output file”: remember that the extension must be .mexw32 and that the file name will be the name of the function under Matlab.

Img6

b. In the same screen we now add the additional Matlab libraries

Img7

As we use a Microsoft Visual C++ compiler in this example, we select versions compatible with Microsoft.

c. We now precise explicitly the libraries to use in “Additional Dependencies” ( “libmat.lib”, “libmex.lib” and “libmx.lib”)

Img8

d. Last we define the “Definition file” for the library

Img9

5. Adding Matlab ressource file

Add the MEX Resource file: “Right click / Add / Existing Item”, add the file “mexversion.rc” from the directory “{$Matlab}/extern/include”.

6. mexFunction

Add a main C/C++ file that will contain the body of “mexFunction” with the following prototype ( do not forget to include the “mex.h” header file to be given access to the prototype of the mexFunction)

Img10

7. Building

Now if you build the project (Right click / “Build”) you end up with a valid mexw32 file to be executed under Matlab. When executing the MEX function “keepPos” in Matlab, the code in this “mexFunction” will be executed.

Following standard coding practices, I use this type of simple template

Img11

8. Example

Here is a first example in C. The header is given by

/*
 *    keepPos.h
 */
 
#include "mex.h"
 
#if !defined(MAX)
#define    MAX(A, B)    ((A) > (B) ? (A) : (B))
#endif
 
#if !defined(MIN)
#define    MIN(A, B)    ((A) < (B) ? (A) : (B))
#endif
 
bool checkOutputs( int nlhs, mxArray *plhs[]);
bool checkInputs( int nrhs, const mxArray*prhs[] );
bool printSyntax();
 
void process( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[] );

and the processing code is

/*
 *    keepPos.cpp
 */
#include "keepPos.h"
 
/* 
* MATLAB entry function 
* Check arguments, outputs and call the real processing function
*/
void mexFunction( int nlhs, mxArray *plhs[], 
                  int nrhs, const mxArray*prhs[] )
{ 
    bool goAhead;
 
    goAhead = checkInputs( nrhs, prhs );
 
    if (goAhead) 
        goAhead = checkOutputs( nlhs, plhs );
 
    if (goAhead)
        process( nlhs, plhs, nrhs, prhs);
 
    return;  
}
 
/* Check Inputs */
bool checkInputs( int nrhs, const mxArray*prhs[] )
{
    bool matrix = (mxGetN(prhs[0]) > 1) && (mxGetM(prhs[0]) > 1);
    if ( (nrhs != 1) || (matrix) )
        return printSyntax();
 
    return true;
}
 
/* Check Outputs */
bool checkOutputs( int nlhs, mxArray *plhs[])
{
    if (nlhs != 1)
        return printSyntax();
 
    return true;
}
 
bool printSyntax()
{
    mexPrintf("\n*********************");
    mexPrintf("\nkeepPos MEX function.");
    mexPrintf("\n*********************");
    mexPrintf("\n-> Purpose :");
    mexPrintf("\n Set all the negative elements to zero");
    mexPrintf("\n");
    mexPrintf("\n-> Syntax :");
    mexPrintf("\nout = keepPos(in)");
    mexPrintf("\nwhere in and out are vectors.");    
    mexPrintf("\n*********************");
    mexPrintf("\nAuthor  : Ben");
    mexPrintf("\nDate    : 8/11/2008");
    mexPrintf("\nVersion : 0.1");
    mexPrintf("\n*********************\n");    
    return false;
}
 
/* Computation function */
void process(   int nlhs, mxArray *plhs[], 
                int nrhs, const mxArray*prhs[] )
{
    const mxArray * data = prhs[0];
    double * vector = mxGetPr(data);
    int n = mxGetN(data);
    int m = mxGetM(data);
    int length = MAX(m,n);
    mxArray * result = mxCreateDoubleMatrix(m,n,mxREAL);
    double * dResult = mxGetPr(result);
 
    for (int loop = 0; loop < length; loop ++)
        dResult[loop] = MAX(vector[loop], 0);        
 
    plhs[0] = result;        
}

This is an interesting example for at least two reasons :

  1. The code is simple and operationnal.
  2. It is a perfect case where it is absolutely pointless to use C/C++ instead of Matlab features. The C code above is in fact (nearly) always slower than the optimised counterpart in Matlab, exposed by Enrico Replacing negative elements of a vector by 0.

9. Outline

  1. Introduction
  2. » Creating a project under Visual C++ Express 2008 «
  3. Basic Principles
  4. Advanced Principles
  5. Conclusion

Internal Links

Concepts
Tutorials
Tips
Related Articles

External links

References
Weblinks

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License