Home Publications Software

Software

Matlab

This page contains some tutorials on compilation of Matlab mex for a number of solverls (LP, QP, MILP, MIQP etc...) which are particolarly usedful in control oriented software (e.g. Hybrid Toolbox and Multi-Parametric Toolbox).
Moreover, some precompiled mex and a general script for compiltion are published and freely availavle.

Compile MEX files directly from package sources

(tested from Matlab r201b 64bit under Windows 7 64bit)
The key idea is to include all sources in the mex compilation so as to avoid annoying linking problems (I also tried to compile the static libraries from sources using mingw64 and, depsite the success, Matlab was unable to link for some wierd reason). In order to compile all source files, a script is used namely make_mex.m which is intented to be used as follows:
  • browse to the folder with the mexfile soruces;
  • copy the package source folder into that folder with your favourite name, in the following that is referred as "source";
  • simply execute from Matlab command window:
    >>make_mex('sources');
Using this method, I compiled for Windows 64bit the mex for the following packages.
  1. CDDLIB 049f
  2. GLPK 4.8
  3. GLPK 4.47
  4. COIN-OR-CLP 1.14.3
If willing to recompile yourself or compiling for a different platform, I list below the sources configured already.
  1. CDDLIB 049f
    The first compiled in this way (thanks to Stefano Di Cairano for pointing out the method). Compile using :
    >>make_mex('lib-src');
    where lib-src is directly the folder from the official release.
  2. GLPK 4.8
    Depending on your operating system, compile using:
    >>make_mex('winsrc');
    for Windows (either 32 or 64 bit) or:
    >>make_mex('unixsrc');
    for Unix (either maci32, maci64, linux32 or linux 64).
  3. GLPK 4.47
    Compile using:
    >>make_mex('src');
    where src is the source folder from the glpk release.
  4. Clp 1.14.3
    A very thoublesome package. In the distribution sources are separated in several folders, but only the following are needed:
    1. BuildTools/headers/headers
    2. Clp/src
    3. CoinUtils/src
    with no subfolder. Moreover, you can remove all files but the ones with extension .c .cpp .h .hpp.
    In order to succeed I also needed to do the following steps:
    • in ClpHelperFunctions:
      - add "#define HAVE_CMATH" before "#ifdef HAVE_CMATH"
    • in ClpSimplex.cpp comment lines 5860-3 if not using the following:
      //#include "ClpCholeskyWssmp.hpp"
      //#include "ClpCholeskyWssmpKKT.hpp"
      //#include "ClpCholeskyUfl.hpp"
      //#include "ClpCholeskyMumps.hpp"
    • in ClpSolve.cpp comments lines 47 and 51:
      //#include "ClpCholeskyUfl.hpp"
      //#include "ClpCholeskyMumps.hpp"
    • in ClpMain.cpp comment lines 2289 467 433:
      //saveSolution(models + iModel, fileName);
      //parameters[iParam].setIntParameter(models + iModel, value);
      //parameters[iParam].setDoubleParameter(models + iModel, value);
    All files listed below are in the $root/Clp/src/ folder.
    NOTE 1: step 1 is used to avoid to pass the define in the mex compile command.
    NOTE 2: if willing to use libraries excluded in steps 2 and 3 some ThirdParty software are needed. In particular: MUMPS, GLPK, CHOLMOD and WSSMP.
    NOTE 3: step 4 is a bad solution to a wired problem. If uncommented those lines gives a linker problem, but the methods are defined and implemented in files included in the compilation. Therefore I had no idea of how to fix it. However it looks like neglecting those lines have no effect in the mex file...
    Note 4: Compiling under OSX I noticed that in file CoinFinite.cpp line 38 should be replaced by:
    return val != COIN_DBL_MAX && val != -COIN_DBL_MAX;
    as constant DBL_MAX have been renamed to COIN_DBL_MAX but in the version update they forgot to change.
With operating system Wiindows 64bit, I noticed that there is not backward compatibility for mex generated with R2010b in R2011b. I suppose this is due to the inclusion of the source files in the mex, instead of simply linking to the static/dynamic librries.

Tutorials

  1. Setup Matlab unix 64bit in MAC OSX 10.7 Lion (or 10.6 Snow Leopard) with Xcode 4.x for mex compilation


    The defult configuration of

    >> mex -setup

    is incapable of properly configure Matlab (up to 2011b) to run with MAC OSX 10.6 and 10.7. The error concerns the name given to the C and C++ compilers and the root directory path. Thus to make it work it is sufficent to properly configure these parameters. Below the list what is to be updated into the file mexopts.sh (by default) located in ~/.matlab/MATLAB_VERSION (MATLAB_VERSION=e.g. R2010b):

    CC='gcc-4.0'
    SDKROOT='/Developer/SDKs/MacOSX10.5.sdk'
    MACOSX_DEPLOYMENT_TARGET='10.5'
    CXX=g++-4.0

    into

    CC='gcc'
    SDKROOT='/Developer/SDKs/MacOSX10.7.sdk'
    MACOSX_DEPLOYMENT_TARGET='10.7'
    CXX=g++

    Replace 10.7 with your operating system version

    XCode 4.3 users should set the SDKROOT as follows:
    SDKROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/'

    A version with applied changes is avaible here mexopts.sh.


  2. Compile Matlab Mex (See this for details) for solvers under unix:



    Solvers covered here are: glpk, cddlib and clp (coin-or) with operating systemm Linux (both 32 and 64 bit)

    • PREREQUITES
      You need to be able to compile mexfiles from Matlab. At the moment of writing (2011/09/23) the latest gcc version supported by Matlab is gcc-4.3.4. Unfortunately, recent linux (in my case Ubuntu) distributions tends to keep-up with latest gcc only and drop support of older gcc version in apt (no easy precompiled versions are avaiable). Thus you need to download the gcc sources, compile them and insall in your system. Note that it may require a lot of time.

      You also need to download the code sources. Below the links:
      GLPK: http://ftp.gnu.org/gnu/glpk/ (usually most recent version is the better)
      COIN-OR CLP: http://www.coin-or.org/download/source/Clp/
      CDDLIB: http://www.ifor.math.ethz.ch/~fukuda/cdd_home/
    • NOTATION
      In the following I will refer to the absolute path of a directory as $dicetory_name.
      A tab character in front of the line indicates a bash command to be executed in the terminal.
      The tag >> indicates a matlab command to be executed from the Matlab command window.
    • Linux 32bit
      • GLPKbr> 1) download glpk in $glpk
        2) cd $glpk
        3) ./configure --with-pic
        4) make
        5) sudo make install
        6) lunch Matlab
        7) >> cd $glpk
        6) >> mex -largeArrayDims -I/usr/local/include glpkcc.cpp /usr/local/lib/libglpk.a
      • CLP
        1) download clp in $clp
        2) cd $clp
        3) ./configure --enable-static
        4) make
        5) sudo make install
        6) launch matlab
        7) >> cd $clp
        8) >> mex -Iinclude/coin -Llib -lClp -lCoinUtils mexclp.cpp
        Note that the include path (-Iinclude/coin) as well as the lib path (-Llib) and lib names (-lClp -lCoinUtils) are RELATIVE, you lunch this from somewhere else than $clp it will not work.
      • CDDLIB
        1) download cddlib in $cddlib
        2) cd $cddlib
        3) ./configure
        4) cd lib-src
        5) make
        6) sudo make install (need to perform installation in /usr/local)
        7) launch matlab
        8) >> cd $cddmex
        9) >> mex -v cddmex.c /usr/local/lib/libcdd.a
    • Linux 64bit
      • GLPK
        1) download glpk in $glpk
        2) cd $glpk
        3) ./configure --with-pic
        4) make
        5) sudo make install
        6) lunch Matlab
        7) >> cd $glpk
        6) >> mex -largeArrayDims -I/usr/local/include glpkcc.cpp /usr/local/lib/libglpk.a
      • CLP
        1) download clp in $clp
        2) cd $clp
        3) ./configure --enable-static --disable-dynamic --disable-shared --with-pic --enable-static-nss
        Note that clp compiles dynamic libraries as defualt option. You do not change this, your mex files will be lighter (smaler file size) but they will only work if you KEEP THE CLP INSTALLATION FILES IN PLACE. Thus I strongly suggest to use the static (libclp.a)
        4) make
        5) sudo make install
        6) launch matlab
        7) >> cd $clp
        8) >> mex -Iinclude/coin -Llib -lClp -lCoinUtils mexclp.cpp
        Note that the include path (-Iinclude/coin) as well as the lib path (-Llib) and lib names (-lClp -lCoinUtils) are RELATIVE, you lunch this from somewhere else than $clp it will not work.
      • CDDLIB
        1) download cddlib in $cddlib
        2) cd $cddlib
        3) CFLAGS=-fPIC;./configure --with-pic CFLAGS=-fPIC --enable-pic --build=x86_64 --target=x86_64 --host=x86_64
        4) cd lib-src
        5) make
        6) sudo make install (need to perform installation in /usr/local)
        7) launch matlab
        8) >> cd $cddmex
        9) >> mex -v cddmex.c /usr/local/lib/libcdd.a
        10) if you are lucky no ld error occurs; otherwise you may try the following steps (note that the gcc calls are relative to my Matlab r2010b installation, those will NOT WORk if you have other Matlab versions installed somewhere else!!!)
        10.1) look at the fisrt gcc call which in my case looks like:
        gcc -c -I/usr/local/MATLAB/R2010b/extern/include -I/usr/local/MATLAB/R2010b/simulink/include -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fexceptions -fPIC -fno-omit-frame-pointer -pthread -DMX_COMPAT_32 -O -DNDEBUG "cddmex.c"
        and call it using the g++ instead:
        >> ! g++ -c -I/usr/local/MATLAB/R2010b/extern/include -I/usr/local/MATLAB/R2010b/simulink/include -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fexceptions -fPIC -fno-omit-frame-pointer -pthread -DMX_COMPAT_32 -O -DNDEBUG "cddmex.c"
        Note that the ! (exclamation mark) is used to call a console command from within Matlab, thus is necessary!
        In my case I had an error in a type casting from void* to char*, that I solved using a (char*) in from of the void* function.
        10.2) now look at the second gcc call (which used the cddmex.o you created with the previous command), in my case:
        gcc -O -pthread -shared -Wl,--version-script,/usr/local/MATLAB/R2010b/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -o "cddmex.mexa64" cddmex.o /usr/local/lib/libcdd.a -Wl,-rpath-link,/usr/local/MATLAB/R2010b/bin/glnxa64 -L/usr/local/MATLAB/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++
        and, as before, replace gcc with g++:
        >> !g++ -O -pthread -shared -Wl,--version-script,/usr/local/MATLAB/R2010b/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -o "cddmex.mexa64" cddmex.o /usr/local/lib/libcdd.a -Wl,-rpath-link,/usr/local/MATLAB/R2010b/bin/glnxa64 -L/usr/local/MATLAB/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++
        In my case it did work! Honestly I guess there is a solution to make the gcc find libcdd.a but it was faster to use g++.

        %% HOW IT FOUND OUT THIS PRETTY BAD LOOKING SOLUTION %%
        Just for the sake of folklore I hereby report the steps I did to figure out the problem. Running the mex (which by the way just works in the 32bit version) I got some wired ld error reporting it cannot find dd_CreateMatrix. I checked its existence and found the definition in cddcore.c; then verifiled the precence in cddcore.o (grep dd_CreateMatrix cddcore.o).
        Then I tried to use the libraries from a simple C++ program, main.cpp :
        #include 
        #include "setoper.h"
        #include "cdd.h"
        int main()
        {
        	int m,n;
        	int i,j;
        	printf("Hello World!!!\n\n");
        	m=1;
        	n=2;
        	dd_MatrixPtr A = dd_CreateMatrix(m, n);
        	for (i = 0; i < m; i++) {
        		for (j = 0; j < n; j++) {
        			dd_set_d(A->matrix[i][j],1);
        		}
        	}
        	printf("Matrix content:");
        	for (i = 0; i < m; i++)
        	{
        		for (j = 0; j < n; j++)
        			printf("%f ",*A->matrix[i][j]);
        		printf("\n");
        	}
        	return 0;
        }
        									
        compiling by calling:
        g++ main.cpp /usr/local/lib/libcc.a
        The DID work just fine.
        I then tried to rename main.cpp in main.c and compiled by
        gcc main.c /usr/local/lib/libcdd.a
        That gave me the error:
        /tmp/ccWL3bGF.o: In function `main':
        main.c:(.text+0x2d): undefined reference to `dd_CreateMatrix'
        main.c:(.text+0x78): undefined reference to `ddd_set_d'
        collect2: ld returned 1 exit status
        Thus I realized that there is an issue is using the function inside the static library (libccd.a) but that is limited to gcc and not g++.
        This gave me the intuition of substituing gcc with g++ in the mex call from within Matlab which led to a succesfull mex creation.
    • Mac OS X 64bit (Snow Leopard)
      • GLPK
        1) download glpk in $glpk
        2) cd $glpk
        3) ./configure --with-pic
        4) make
        5) sudo make install
        6) lunch Matlab
        7) >> cd $glpk
        6) >> mex -largeArrayDims -I/usr/local/include glpkcc.cpp /usr/local/lib/libglpk.a
      • CLP
        1) download clp in $clp
        2) cd $clp
        3) ./configure --enable-static --disable-dynamic --disable-shared --with-pic
        4) make
        5) sudo make install
        6) launch matlab
        7) >> cd $clp
        8) >> mex -Iinclude/coin -Llib -lClp -lCoinUtils mexclp.cpp
        Note that the include path (-Iinclude/coin) as well as the lib path (-Llib) and lib names (-lClp -lCoinUtils) are RELATIVE, you lunch this from somewhere else than $clp it will not work.
      • CDDLIB
        1) download cddlib in $cddlib
        2) cd $cddlib
        3) CFLAGS=-fPIC;./configure --with-pic CFLAGS=-fPIC --enable-pic --build=x86_64 --target=x86_64 --host=x86_64
        4) cd lib-src
        5) make
        6) sudo make install (need to perform installation in /usr/local)
        7) launch matlab
        8) >> cd $cddmex
        9) >> mex -v -I/usr/local/include cddmex.c /usr/local/lib/libcdd.a
        Note that you have to copy cddmex.c into the latter folder
        10) make sure that the mex is not a few kilobytes only otherwise that is dynamically linked. If so do the following:
        10.1) >> mex -v -Iinclude/coin -Llib -lClp -lCoinUtils -lbz2 -lz -lm mexclp.cpp
        10.2) launch the first g++ command from the matlab command window as the mex call does, in my case:
        >> ! g++ -c -Iinclude/coin -I/Applications/MATLAB_R2010b.app/extern/include -I/Applications/MATLAB_R2010b.app/simulink/include -DMATLAB_MEX_FILE -fno-common -no-cpp-precomp -fexceptions -arch x86_64 -isysroot /Developer/SDKs/MacOSX10.6.sdk -mmacosx-version-min=10.6 -DMX_COMPAT_32 -O2 -DNDEBUG "mexclp.cpp"
        then take the second command as substitute gcc with g++, then add the following to the end: -framework vecLib
        >> ! g++ -O -Wl,-twolevel_namespace -undefined error -arch x86_64 -Wl,-syslibroot,/Developer/SDKs/MacOSX10.6.sdk -mmacosx-version-min=10.6 -bundle -Wl,-exported_symbols_list,/Applications/MATLAB_R2010b.app/extern/lib/maci64/mexFunction.map -o "mexclp.mexmaci64" mexclp.o -Llib -lClp -lCoinUtils -lbz2 -lz -lm -L/Applications/MATLAB_R2010b.app/bin/maci64 -lmx -lmex -lmat -lstdc++ -framework vecLib
        This should create a mex file of the size of about 2MB.
    • Compile mex files in Windows


      Matlab for Windows comes with a default compiler for 32bit but needs Visual Studio (Visual C++) for compile 64 bit executables. Moreover, for recent versions, also Windows SDK components are needed.
      Note that, as pointed out in the Mathworks official web page, each Visual Studio version (both Express, given freely, and Full, for purchase) requires a different version of the Windows SDK. In fact, VS 2008 requires SDK 6.x while VS 2010 requires SDK 7.x.

Use C / C++ code from Matlab

  • 	/**
    	 Simple c standard function used for demonstrate how to pass parameters and return string output.
    	 The function reads the number of parameters (passed as space-separated string) and outputs the received
    	 string along with integer and double conversion.
    	 Main drawback is that you use a very inefficient parameter passing method, in both ways,
    	 since you have to build command call the string in Matlab and then parse the results.
    	 The goood point is that it is totally architecture independent, in fact, povided that you have
    	 a compiled version of your c-based code, you can execute from whitin Matlab and further work is
    	 required.
    	 
    	 */
    	
    	#include 
    	//used for string to int/double conversion
    	#include 
    	
    	int main(int argc, char* argv[])
    	{
    		if (argc<=1)
    			printf("No parameters!!!\n");
    		else
    		{
    			int i,ni;
    			double nf;
    			for(i=1;i< argc;i++)
    			{
    				printf("The %d-th  parameter is %s\n",i,argv[i]);
    				ni=atoi(argv[i]);
    				nf=atof(argv[i]);
    				printf("Corresponding int: %d\tdouble:%f\n",ni,nf);
    			}
    		}
    		printf("\n");
    		return 0;
    	}
    								
  • 	#include "mex.h"
    	/*
    	 * Let us assume you want to pass the follwing parameters to your mex file:
    	 * - 1 double;
    	 * - 1 array of double whose size is inherited from Matlab
    	 *
    	 * This is a modification of the example you can find in 
    	 * http://www.mathworks.com/help/techdoc/matlab_external/f29502.html
    	 */
    	// this is the use you make of the code: i.e. scalar-array product
    	void my_mex(double x, double *y, double *z, mwSize n) {
    	    mwSize i;
    	    
    	    for (i=0; i< n; i++) {
    	        z[i] = x * y[i];
    	    }
    	}
    	/* The gateway function */
    	// you don't need to change this function name nor its paramaters, as they
    	// are number of  elements and elements pointers for lines and rows,
    	// respectively
    	void mexFunction( int nlhs, mxArray *plhs[],
    	        int nrhs, const mxArray *prhs[]) {
    	    /* here you declare the variable you know you will receive from input*/
    	    double multiplier;      /* input scalar */
    	    double *inMatrix;       /* 1xN input matrix */
    	    mwSize ncols;           /* size of matrix */
    	    //output matrix delaration
    	    double *outMatrix;      /* output matrix */
    	    /* check for proper number of arguments */
    	    if(nrhs!=2) {
    	        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs",
    	                "Two inputs required.");
    	    }
    	    if(nlhs!=1) {
    	        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs",
    	                "One output required.");
    	    }
    	    /* make sure the first input argument is scalar: is double, not complex and scalar */
    	    if( !mxIsDouble(prhs[0]) ||
    	            mxIsComplex(prhs[0]) ||
    	            mxGetNumberOfElements(prhs[0])!=1 ) {
    	        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notScalar",
    	                "Input multiplier must be a scalar.");
    	    }
    	    /* check that number of rows in second input argument is 1 */
    	    if(mxGetM(prhs[1])!=1) {
    	        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector",
    	                "Input must be a row vector.");
    	    }
    	    /* get the value of the scalar input  */
    	    multiplier = mxGetScalar(prhs[0]);
    	    /* create a pointer to the real data in the input matrix  */
    	    inMatrix = mxGetPr(prhs[1]);
    	    /* get dimensions of the input matrix */
    	    ncols = mxGetN(prhs[1]);
    	    /* create the output matrix */
    	    plhs[0] = mxCreateDoubleMatrix(1, ncols, mxREAL);
    	    /* get a pointer to the real data in the output matrix */
    	    outMatrix = mxGetPr(plhs[0]);
    	    /* call your c-code function passing parameters as it expects */
    	    my_mex(multiplier, inMatrix, outMatrix, ncols);
    	}
    							


You may use the following Matlab code to test the two previous approaches:
	%% Standard C/C++ parameter passing against Matlab mex
	%
	% The purpose is to execute a code written in C/C++ from whitin the Matlab
	% environment, passing some parameters and getting an answer, possibly
	% not single nor scalar.
	%
	% Depsite using operating system dependent tools, such as serial port or
	% ethernet simulated transmissions, the way (at lest to the writer
	% knowledgge) are the following:
	%
	% * call the precompiled executable file from Matlab by means of the
	% command "system"
	%
	% * write a mex file which includes the custom C/C++ code and use the
	% the function just as any Matlab function.
	
	%% Standard C parameter passing
	% Prepare the command string to be executed
	disp('Standard C');
	cmd=[];
	if ispc()
	    cmd=[cmd 'c_standard.exe'];
	else
	    cmd=[cmd './c_standard'];
	end
	
	% use 0 for no input parameters
	if 1
	    cmd=[cmd ' 1 2.3 4'];
	end
	
	% call the system with the prepared command
	[err_code str_out]=system(cmd);
	str_out
	
	%% Use of the mex file
	disp('Mex call');
	result=my_mex(2.2,[2 3.4 5 6.7])
	% Note that this latter way is much faster, but probably requires more time
	% than the other as a compiled mex is needed for every metlab
	% version/operating system
	% try to change the my_mex call and see what happend.					
						
As a general comment (pointed out by Stefano Di Cairano), I should say that in Standard C variable declaration is only allowed in appropriate places in the code, i.e. immediately after a '{'. Current generation compilers, as gcc, are not formal about that, but Visal C (cl.exe) is. One simple, practical way to solve it is to rename the file extension to .cpp where the restriction does not apply.
  • BGL Toolbox for Matlab is a powerfull tool which comes with many precompiled mex files, i.e. win32, win64, linux32, linux64, mac and maci. However, mexmaci64 are missing at the tiem of writing, thus if you need to use the tool in a 64 bit version of Matlab running under Mac OSX you need to compile you own (or just donwload form the list at the end of this page). To do so you may donwload from here a version of the sources which support large arrays. Note that in order to run the compile.m file form Matlab, from the folder "private", you need to have the libmbgl compiled for your system, i.e. the file "libmbgl-macosx-intel-64-large.a". To do so you need to browse to $BGL_inst_dir/libmbgl and run compile-macosx-intel-64-large.sh. Note that is call the boost installation as "BOOST_DIR=${HOME}/dev/lib/boost_1_36_0/", therefore you need to download boost and put in that folder.
    For the sake of folkore I have to report that I tried with boost_1_46_0 and got some wired errors complaining for some missing files.

    List of downloadable compiled mex files


    Let me know if you encounter any issue.

    GLPK - 4.47
    GLPK - 4.8
    COIN-CLP
    CDD
    BGL Note that some of the listed mex are not yet been added to the website

  • To compile those mex files you need the following statically precompiled libraries…

    MAC OSX 64bit (Snow Leopard)
    MAC OSX 32bit (Leopard)
    • To be done

    Linux 32bit (Ubuntu 11.04)
    • To be done

    Linux 64bit (Ubuntu 11.04)
    • To be done
    Windows 32bit (XP)
    • To be done

    Windows 64bit (7)
    • To be done
  • Comments/suggestions are wellcome at barcelli [a t ] dii.unisi.it