DIPimage User Manual » DIPimage and the MATLAB Compiler

The MATLAB Compiler

Since MATLAB version 7.0 (Release 14), the MATLAB Compiler no longer generates C or C++ code from M-files. Instead, it packages all M-files and MEX-files into a Component Technology File (CTF) archive, generates a small stub executable, and requires the end user to install the MATLAB Component Runtime (MCR). This MCR is the MATLAB interpreter (but without licensing restrictions). The upside of this is that there are no longer limitations as to what M-files can be compiled, meaning it is now possible to create standalone applications that use DIPimage. The downside is that, since code is not really compiled, there is no performance benefit to compiling.

The MATLAB compiler can generate shared objects (dynamically linked libraries) as well as executables. This means that it is still possible to compile M-file code so that it can be called from your own C or C++ code, even though this compiled M-file code can no longer be statically linked into your executable.

M-files in the CTF archive are encrypted so that it is not possible to obtain source code from the compiled application. MEX-files are also protected in some way so they cannot be run outside of the deployed application. Therefore, even though the code is not truly compiled, your code is reasonably well protected against reverse-engineering.

The explanations below are for Linux/UNIX systems. If you use Windows, similar issues will have to be taken into account. The MATLAB Compiler User's Guide (available online at https://www.mathworks.com/help/pdf_doc/compiler/compiler.pdf) contains all the information needed to compile an M-file that uses DIPimage.

Compiling an M-file that uses DIPimage

Please first read the MATLAB Compiler User's Guide, and make sure you are able to generate the magicsquare.m stand-alone example application using the mcc command (not through the deploytool GUI, since the explanations below assume you are familiar with mcc).

There are a few things that have to be taken into account when your M-file uses DIPimage. First, like with other toolboxes, the DIPimage directory must not be added to the MATLAB path through the startup.m file (as suggested in the DIPimage installation instructions), but through the mcc command line. Second, instead of calling dip_initialise, call dip_initialise_libs.

dip_initialise searches for the correct version of the DIPimage toolbox to use, depending on the MATLAB version you are running. It then adds the necessary paths and calls dip_initialise_libs. Since this process doesn't work with the MATLAB Compiler, you will need to do these two steps separately.

Hence, you need to create a special version of your startup.m file in the directory where your application M-file lives. Remove all the addpath instructions, and change the line dip_initialise into dip_initialise_libs (if you do not want the DIPlib version information to be displayed on startup, you can use the 'silent' argument to dip_initialise_libs). Alternatively, you can call the dip_initialise_libs function in your application M-file. In this case, make and empty startup.m file to avoid your default one to be used.

To find out which directories you need to add to the Compiler search path, type path on the MATLAB command line. It should return a long list of directories, three of which look like this:

/something/dip/common/mlv7_4/diplib
/something/dip/common/mlv7_4/dipimage_mex
/something/dip/common/dipimage

These three paths can be added the the mcc command line using the '-I' argument:

mcc -m myapplication.m ...
    -I /something/dip/common/dipimage ...
    -I /something/dip/common/mlv7_4/dipimage_mex ...
    -I /something/dip/common/mlv7_4/diplib

Under some circumstances, mcc might give a warning telling you that the dip_initialise_libs command is unknown. However, when running the resulting executable, DIPlib gets initialized just fine. This must be due to the order in which paths get added and commands are executed.

When running the stand-alone application you just created, the three DIPlib shared libraries must be on the LD_LIBRARY_PATH environment variable, as discussed in UNIX/Linux installation. It is possible to edit the shell script that is created by mcc (run_myapplication.sh) to properly set the LD_LIBRARY_PATH environment variable.

Deploying your compiled program

First of all, note that you need a special license of DIPimage and DIPlib to be able to distribute a program that uses this toolbox and associated libraries. Please read our web page (http://www.diplib.org/) for information on how to obtain such a license.

The CTF file created by mcc needs either the exact same version of MATLAB, or the MCR created with that version, to run. It will also need the three DIPlib shared libraries libdip.so, libdipio.so and libdml_mlvX_X.so (the name of this last SO file should match the directory name given as path to the MATLAB Compiler). The end-user needs to install these three libraries and adjust the LD_LIBRARY_PATH environment variable prior to starting the executable.

There is a very simple way of including the DIPlib libraries in the CTF file:

mcc -m myapplication.m ...
    -I /something/dip/common/dipimage ...
    -I /something/dip/common/mlv7_4/dipimage_mex ...
    -I /something/dip/common/mlv7_4/diplib ...
    -a /something/dip/Linux/libdip.so ...
    -a /something/dip/Linux/libdipio.so ...
    -a /something/dip/Linux/libdml_mlv7_4.so

The CTF archive will be called myapplication.ctf, and, once extracted, the DIPlib libraries will be in the directory myapplication_mcr/something/dip/Linux/ (assuming 32-bit Linux OS).

Thus, assuming your user puts the files myapplication.ctf and myapplication into the directory /home/user/myapp/, and installed the MCR into /usr/local/mcr/v76/, your user will have to do the following to start the application:

MCRROOT=/usr/local/mcr/v76
LD_LIBRARY_PATH=/home/user/myapp/myapplication_mcr/something/dip/Linux/
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRROOT}/runtime/glnx86
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRROOT}/bin/glnx86
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRROOT}/sys/os/glnx86
MCRJREVER=`cat ${MCRROOT}/sys/java/jre/glnx86/jre.cfg`
MCRJRE=${MCRROOT}/sys/java/jre/glnx86/jre${MCRJREVER}/lib/i386
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRJRE}/native_threads
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRJRE}/server
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRJRE}/client
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRJRE}
XAPPLRESDIR=${MCRROOT}/X11/app-defaults
export LD_LIBRARY_PATH
export XAPPLRESDIR /home/user/myapp/myapplication <arguments>

You would do good creating a little shell script that collects these commands, and provide it with your executable (instead of run_myapplication.sh).

Note that, in the shell commands above, the ones that contain MCRJRE are needed only if Java is enabled. You can add -R -nojvm to the mcc command to disable Java if your application does not use it. In the same way, add -R -nodisplay if your application does not use the graphic display.