Overview of the MATLAB Compiler » History » Version 1
Chris Cannam, 2014-03-11 03:11 PM
1 | 1 | Chris Cannam | h1. Overview of the MATLAB Compiler |
---|---|---|---|
2 | 1 | Chris Cannam | |
3 | 1 | Chris Cannam | h2. What it is |
4 | 1 | Chris Cannam | |
5 | 1 | Chris Cannam | The "MATLAB compiler" is a program called "mcc" that ships with MATLAB. It compiles MATLAB code into (encrypted) binary code for the current platform. That is, it appears you must compile on the same machine architecture and operating system as you want to use the code on -- it doesn't cross-compile. You can then take this code to a different machine and run it using the (free) MCR runtime. |
6 | 1 | Chris Cannam | |
7 | 1 | Chris Cannam | The compiler has a pretty wide range of options, described in the command-line help text (run @mcc -?@). Note that there are examples at the bottom of the help. |
8 | 1 | Chris Cannam | |
9 | 1 | Chris Cannam | The most basic usage is |
10 | 1 | Chris Cannam | |
11 | 1 | Chris Cannam | <pre> |
12 | 1 | Chris Cannam | $ mcc -m function |
13 | 1 | Chris Cannam | </pre> |
14 | 1 | Chris Cannam | |
15 | 1 | Chris Cannam | to compile the MATLAB file @function.m@ into a standalone executable. |
16 | 1 | Chris Cannam | |
17 | 1 | Chris Cannam | h3. Executing the file |
18 | 1 | Chris Cannam | |
19 | 1 | Chris Cannam | If the compiled file is called @foo.exe@, it should be called as: |
20 | 1 | Chris Cannam | |
21 | 1 | Chris Cannam | <pre> |
22 | 1 | Chris Cannam | foo.exe arg1 arg2 |
23 | 1 | Chris Cannam | </pre> |
24 | 1 | Chris Cannam | |
25 | 1 | Chris Cannam | *Note* that MATLAB assumes that *all arguments to be strings*, so if you are expecting doubles, integers, etc these should be *handled inside the function*. For instance, if arg1 is an integer, one can do the conversion using |
26 | 1 | Chris Cannam | |
27 | 1 | Chris Cannam | <pre> |
28 | 1 | Chris Cannam | if ischar(arg1) |
29 | 1 | Chris Cannam | arg1=str2num(arg1); |
30 | 1 | Chris Cannam | end |
31 | 1 | Chris Cannam | </pre> |
32 | 1 | Chris Cannam | |
33 | 1 | Chris Cannam | Read more (including how to use matrices as arguments) here: |
34 | 1 | Chris Cannam | |
35 | 1 | Chris Cannam | http://www.mathworks.co.uk/support/solutions/en/data/1-18448/?solution=1-18448 |
36 | 1 | Chris Cannam | |
37 | 1 | Chris Cannam | |
38 | 1 | Chris Cannam | h2. How to run the result on a different machine |
39 | 1 | Chris Cannam | |
40 | 1 | Chris Cannam | The "target" machine doesn't have to have MATLAB installed or a MATLAB licence. You will need to install the "MCR runtime":http://www.mathworks.co.uk/help/compiler/working-with-the-mcr.html, but you don't need to be root to do it -- you can just install into a random directory somewhere. If you're doing that, note that the installer puts all manner of crap directly in the directory you give it, so be sure to make a new directory for it. |
41 | 1 | Chris Cannam | |
42 | 1 | Chris Cannam | If you run @ldd@ or @otool -L@ (depending on platform) on your compiled binary, you'll see that it depends on various shared libraries: |
43 | 1 | Chris Cannam | |
44 | 1 | Chris Cannam | <pre> |
45 | 1 | Chris Cannam | libmwlaunchermain.so => not found |
46 | 1 | Chris Cannam | libmwmclmcrrt.so.8.1 => not found |
47 | 1 | Chris Cannam | libmwcpp11compat.so => not found |
48 | 1 | Chris Cannam | </pre> |
49 | 1 | Chris Cannam | |
50 | 1 | Chris Cannam | You get these (in two separate locations, a @bin@ and a @runtime@) when you install the MCR. You can make the executable run by adding both locations to the @LD_LIBRARY_PATH@ when you run it. The MCR comes with lots of instructions, but you don't really need them if you don't want a GUI. |
51 | 1 | Chris Cannam | |
52 | 1 | Chris Cannam | (The default compiled application is very slow to start up, and will either need additional configuration for GUI support or else will complain about the lack of it when it starts. Adding the @-R -nojvm -R -nodisplay@ options to the @mcc@ command-line should fix this, assuming a GUI is not in fact required.) |
53 | 1 | Chris Cannam | |
54 | 1 | Chris Cannam | h2. Creating a C++ shared library |
55 | 1 | Chris Cannam | |
56 | 1 | Chris Cannam | http://blogs.mathworks.com/loren/2011/02/03/creating-c-shared-libraries-and-dlls/ |
57 | 1 | Chris Cannam | |
58 | 1 | Chris Cannam | On OSX I had to add the following to @DYLD_LIBRARY_PATH@: |
59 | 1 | Chris Cannam | |
60 | 1 | Chris Cannam | <pre> |
61 | 1 | Chris Cannam | /Applications/MATLAB_R2011a.app/runtime/maci64/:/Applications/MATLAB_R2011a.app/bin/maci64/:/Applications/MATLAB_R2011a.app//sys/os/maci64/ |
62 | 1 | Chris Cannam | </pre> |
63 | 1 | Chris Cannam | |
64 | 1 | Chris Cannam | h3. Creating the shared library |
65 | 1 | Chris Cannam | |
66 | 1 | Chris Cannam | |
67 | 1 | Chris Cannam | |
68 | 1 | Chris Cannam | (Example for the following code, using OSX 10.7.5 and MATLAB_R2011a) |
69 | 1 | Chris Cannam | |
70 | 1 | Chris Cannam | File gensin.m: |
71 | 1 | Chris Cannam | <pre> |
72 | 1 | Chris Cannam | function gensin(freq) |
73 | 1 | Chris Cannam | %% generates a 2 second long sine wave of a given frequency |
74 | 1 | Chris Cannam | % freq should be in Hz |
75 | 1 | Chris Cannam | % writes the output to file out.wav |
76 | 1 | Chris Cannam | |
77 | 1 | Chris Cannam | if ischar(freq) |
78 | 1 | Chris Cannam | freq=str2double(freq); |
79 | 1 | Chris Cannam | else |
80 | 1 | Chris Cannam | freq=double(freq); |
81 | 1 | Chris Cannam | end |
82 | 1 | Chris Cannam | |
83 | 1 | Chris Cannam | fs = 44100; |
84 | 1 | Chris Cannam | t = 0:1/fs:2; % 2 second clip |
85 | 1 | Chris Cannam | |
86 | 1 | Chris Cannam | y = sin(2*pi*freq.*t); |
87 | 1 | Chris Cannam | |
88 | 1 | Chris Cannam | % writes the file - NBITS = 16 |
89 | 1 | Chris Cannam | wavwrite(y, fs, 'out.wav'); |
90 | 1 | Chris Cannam | |
91 | 1 | Chris Cannam | end |
92 | 1 | Chris Cannam | </pre> |
93 | 1 | Chris Cannam | |
94 | 1 | Chris Cannam | h3. Generating the library |
95 | 1 | Chris Cannam | |
96 | 1 | Chris Cannam | <pre> |
97 | 1 | Chris Cannam | /Applications/MATLAB_R2011a.app/bin/mcc -W cpplib:libmysine -T link:lib gensin |
98 | 1 | Chris Cannam | </pre> |
99 | 1 | Chris Cannam | |
100 | 1 | Chris Cannam | This will create several files: |
101 | 1 | Chris Cannam | |
102 | 1 | Chris Cannam | * libmysine.h |
103 | 1 | Chris Cannam | * libmysine.cpp |
104 | 1 | Chris Cannam | * libmysine.dylib |
105 | 1 | Chris Cannam | * libmysine.exports |
106 | 1 | Chris Cannam | * mccExcludedFiles.txt |
107 | 1 | Chris Cannam | * readme.txt |
108 | 1 | Chris Cannam | |
109 | 1 | Chris Cannam | h3. An example c++ program |
110 | 1 | Chris Cannam | |
111 | 1 | Chris Cannam | <pre> |
112 | 1 | Chris Cannam | // testsin.cpp: generate a 2 sec sine wave |
113 | 1 | Chris Cannam | // code to exemplify how to use MATLAB code as a C++ library |
114 | 1 | Chris Cannam | // |
115 | 1 | Chris Cannam | // Example adapted from: |
116 | 1 | Chris Cannam | // http://blogs.mathworks.com/loren/2011/02/03/creating-c-shared-libraries-and-dlls/ |
117 | 1 | Chris Cannam | // and http://www.mathworks.com/matlabcentral/answers/1720 |
118 | 1 | Chris Cannam | |
119 | 1 | Chris Cannam | #include "libmysine.h" |
120 | 1 | Chris Cannam | #include <iostream.h> |
121 | 1 | Chris Cannam | |
122 | 1 | Chris Cannam | int run_main(int argc, const char *argv[]) |
123 | 1 | Chris Cannam | { |
124 | 1 | Chris Cannam | // I expecty only one argument which is the frequency |
125 | 1 | Chris Cannam | |
126 | 1 | Chris Cannam | // Initialize the MATLAB Compiler Runtime global state |
127 | 1 | Chris Cannam | if (!mclInitializeApplication(NULL,0)) |
128 | 1 | Chris Cannam | { |
129 | 1 | Chris Cannam | std::cerr << "Could not initialize the application properly." |
130 | 1 | Chris Cannam | << std::endl; |
131 | 1 | Chris Cannam | return -1; |
132 | 1 | Chris Cannam | } |
133 | 1 | Chris Cannam | |
134 | 1 | Chris Cannam | // Initialize the MySine library |
135 | 1 | Chris Cannam | if( !libmysineInitialize() ) |
136 | 1 | Chris Cannam | { |
137 | 1 | Chris Cannam | std::cerr << "Could not initialize the library properly." |
138 | 1 | Chris Cannam | << std::endl; |
139 | 1 | Chris Cannam | return -1; |
140 | 1 | Chris Cannam | } |
141 | 1 | Chris Cannam | |
142 | 1 | Chris Cannam | // Must declare all MATLAB data types after initializing the |
143 | 1 | Chris Cannam | // application and the library, or their constructors will fail. |
144 | 1 | Chris Cannam | |
145 | 1 | Chris Cannam | // 100 Hz |
146 | 1 | Chris Cannam | mwArray freq(100); |
147 | 1 | Chris Cannam | |
148 | 1 | Chris Cannam | gensin(freq); |
149 | 1 | Chris Cannam | |
150 | 1 | Chris Cannam | libmysineTerminate(); |
151 | 1 | Chris Cannam | |
152 | 1 | Chris Cannam | mclTerminateApplication(); |
153 | 1 | Chris Cannam | return 0; |
154 | 1 | Chris Cannam | } |
155 | 1 | Chris Cannam | |
156 | 1 | Chris Cannam | int main() { |
157 | 1 | Chris Cannam | mclmcrInitialize(); |
158 | 1 | Chris Cannam | return mclRunMain((mclMainFcnType)run_main,0,NULL); |
159 | 1 | Chris Cannam | } |
160 | 1 | Chris Cannam | </pre> |
161 | 1 | Chris Cannam | |
162 | 1 | Chris Cannam | h3. Compiling the C++ source with the library |
163 | 1 | Chris Cannam | |
164 | 1 | Chris Cannam | In order to do this you should use *mbuild*: |
165 | 1 | Chris Cannam | |
166 | 1 | Chris Cannam | <pre> |
167 | 1 | Chris Cannam | /Applications/MATLAB_R2011a.app/bin/mbuild testsin.cpp libmysine.dylib |
168 | 1 | Chris Cannam | </pre> |