Compile MATLAB .m files to a stand-alone C/C++ applications
This is applicable to MATLAB 6.5+ on Windows and MATLAB R2008a on Mac OS X. First, we should have MATLAB Compiler as an installed component.
Step 1. Setup the MATLAB Compiler using
mbuild -setup
For Windows, we should indicate the C/C++ compiler we want to use: Microsoft Visual C++ or whatever was installed in our machine; or Lcc incorporated in MATLAB Compiler.
For Intel Mac, we do not need to do anything since gcc and g++ are by defaults C and C++ compilers.
Step 2. Compile the MATLAB source code using
mcc -m file1.m file2.m file3.m file4.m
where file*.m are all files required for the application to be stand-alone. They are expected to be mutually dependent. The command, if successful, produces an platform-dependent executable file whose name is from the .m contains the main flow- not a function file.
Important: this command also produces a .ctf file which contains the required MATLAB functions in the application. This file is extremely important when we distribute our application to other machine.
Step 3. Test the application
For Windows, we should update the MATLAB path to the system or user paths by going to Control Panel/System/Advanced/Environment Variables/, selecting variable 'path' and click Edit. Add <MATLAB>\bin\win32 to the paths.
For Unix, we should add the MATLAB dynamic linked library paths into the system DYLD_LIBRARY_PATH in the ~/.bashrc and then make it become effective by using:
source ~/.basrc
The updated ~/.bashrc should look like:
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:<MATLAB>/run time/maci
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:<MATLAB>/bin/maci
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:<MATLAB>/sys/os/maci
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/System/Library/Frameworks/JavaVM.frameworks/JavaVM
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/System/Library/Frameworks/JavaVM.frameworks/Libraries
export XAPPLRESDIR=$XAPPLRESDIR:<MATLAB>/X11/app-defaults
Note: on Intel Mac, there may be some warnings about duplicate directory names or no latest version of app-default files. We can ignore all of these!
Run the application as we usually do! (from command line, double click, etc.)- If the application require input parameters, we should provide them, of course.
Step 4. Distribute our application to other machines without MATLAB
Remember that we can only ship our application to other machines running the same platform. For instance, if the application is built by MATLAB on Windows, then it can only run on Windows.
For Windows, package the MCRInstaller.exe file, the .ctf file and the executable file.
For Mac OS X, package the MCRInstaller.dmg file, the .ctf file and the executable file.
As we run the application, the executable file looks up the .ctf file for the required functions. The .ctf file in turn unzips the MCRInstaller.exe/MCRInstaller.dmg file, which is an archive, and calls the appropriate functions as needed. (FYI: MCR stands for MATLAB Compiler Runtime.)
Compile and build a library from MATLAB
There are two tasks that need to be accomplished. The first is to export MATLAB functions to a dynamic linked library (.dll). The second one is to encapsulate the implementation of MATLAB-dependent types into a wrapper dynamic linked library.
Let assume that we are to export two functions func1 and func2 in the corresponding files.
Step 1. Exporting functions by mcc in MATLAB (6.0 and later):
mcc -t -L C -W lib:namelib -T link:lib func1.m func2.m libmmfile.mlib
which produces the following files:
func1.c
func2.c
func1.h
func2.h
namelib.c
namelib.h
namelib.exports
namelib.lib
namelib.dll
namelib.exp
namelib.mlib
Note:
i) List of functions should include all involved functions in the first two functions (if required, e.g. "butter.m" requires lp2hp, bilinear, etc.)
ii) Often, functions calling private sub-functions will produde linking error when compling because these sub-funcs are put in the PRIVATE directory of the toolbox. So, COPY and RENAME this PRIVATE directory and Set Path to this new directory. If do this, you can skip such private functions in the above list or overlapping funcs on-your-own.
Step 2. Creating a Win32 DLL Application in VC++
1. Project\Settings:
C/C++ Tab: Category: Code Generation: Multithreaded DLL
C/C++ Tab: Preprocessor:
- Preprocessor definitions += ,MSVC,MSWIND,IBMPC (03 items)
- Additional include directories: (03 items)
<MATLAB>\extern\include;<MATLAB>\extern\include\cpp;
<Path to namelib.h>
2. Project\Add to Project\Files: (04 files)
namelib.lib
<MATLAB>\extern\lib\microsoft\msvc60\libmmfile.lib;
<MATLAB>\extern\lib\microsoft\msvc60\libmx.lib;
<MATLAB>\extern\lib\microsoft\msvc60\libmatlb.lib;
3. Create functions that encapsulate all the MATLAB exported functions (whose argument are of mxArray* type) in 02 files
i, file .h: for function interface (e.g. Interface.h)
ii, file .cpp: for implementation:
include files: (03 items)
#include "matlab.h"
#include "namelib.h"
#include "Interface.h"
Ex. encapsulate:
mxArray* mlfFFT(mxArray* x, mxArray* n);
in
double* __stdcall FFT(double* x, int n);
Important notes:
1. To convert double or int to mxArray* (for Matlab function calls)
double value = 10.0;
mxArray* value_ptr;
x_ptr = mxScalar(value);
2. To convert double* to mxArray* (for Matlab function calls)
int nCols = 512;
double* x[nCols]; // populated
mxArray* x_ptr;
x_ptr = mxCreateDoubleMatrix(1, nCols, mxREAL);
memcpy(x_ptr, x, sizeof(double)*nCols);
3. To convert from mxArray* to double* (for returning results)
int nCols = 512;
double* y[nCols];
mxArray* y_ptr;
...
y_ptr = mlfMyFunction(); // returned from functions
memcpy(y, y_ptr, sizeof(double)*nCols);
4. Create .def file for DLL (to export them to .lib file and .dll): (if not, there will be a linking error: un-resolved external object...)
LIBRARY "FFT"
DESCRIPTION 'Fast Fourier Transform'
EXPORTS
FFT
5. Build .dll
Use the dynamics linked library in a client application
1. Copy these following files to the client application folder: (04 files)
- .lib (just built)
- .h (just built)
- .dll (just built) (to the same location as the executable)
- namelib.dll (built by mcc in Step 1) (to the same location as the executable)
2. Add to client project: the .lib file
Indicate in the linking options:
/NODEFAULTLIB:libc.lib
/NODEFAULTLIB:libcmt.lib
/NODEFAULTLIB:libcd.lib
/NODEFAULTLIB:libcmtd.lib
/NODEFAULTLIB:msvcrtd.lib