I would like to build a shared library from my MATLAB code and use that with my larger application under UNIX.
MATLAB: How to create a C shared library using MATLAB Compiler 6.5 (R13) and use it with the C application
.sobuildcompilerdlldynamiclibrarylinuxMATLABMATLAB Compilersharedsolarisunix
Related Solutions
The steps to create a C shared library from within MATLAB are:
1. Select the compiler to be used by MCC:
mbuild -setup
2. Compile your MATLAB files into a DLL (on Windows):
mcc -B csharedlib:mylib <MATLAB files>
The -B csharedlib option is a bundle option that expands into
-W lib:<libname> -T link:lib
The -W lib:<libname> option tells the MATLAB Compiler to generate a function wrapper for a shared library and call it libname. The -T link:lib option specifies the target output as a shared library.
Note the directory where the Compiler puts the shared library because you will need it later on. This step will produce mylib.dll, mylib.lib, and mylib.h. You can add the -g option to produce a DLL suitable for debugging in MSVC (or your own IDE).
Alternatively, you may also use DEPLOYTOOL and choose C Shared library as the target to achieve this.
3. Add mylib.lib to your MSVC (or your own IDE) project.
4. Make sure to call the initialization and termination routines from your code before calling any of the exported DLL functions.
To initialize the shared library and the MCR, you need to call:
mclInitializeApplication(NULL,0);mylibInitialize();
Afterwards, you should call the termination routine:
mclTerminateApplication();mylibTerminate();
5. You can call the functions compiled from the MATLAB code by invoking the exported DLL functions from your C code. For example:
Example:
In MATLAB:
1. Write a MATLAB function named foo and save it as foo.m with the following code:
function y = foo(x)y = x+1;
2. Select the compiler to be used by MCC:
mbuild -setup
3. Use the MATLAB Compiler to compile foo.m into C code that can be included in a C shared library:
mcc -B csharedlib:foolib foo.m
This will generate the following files:
foolib.ctf
foolib.h
foolib.dll
foolib.lib
foolib.exp
foolib_mcc_component_data.c
foolib.c
foolib.exports
In Microsoft Visual 2010 Express Edition
1. Start the Microsoft Visual 2010 Express Edition IDE.
2. Go to FILE and NEW. In the Project Types field, select Visual C++ Projects. In the Templates field, select Win32 Console Project. In the Name field type "test". Click OK. In the Win32 application Wizard, select Application Settings. Under Additional Options, check Empty project. Click Finish.
3. Select the Solution Explorer tab. Select Source Files, select Project menu option, select Add New Item. In the Templates tab select C++ Source file, type "foowrap.c" in the File name field and click Open.
4. Enter the following code in the foowrap.c file:
/* Include the MCR header file and the library specific header file* as generated by MATLAB Compiler */#include "mclmcr.h" #include "foolib.h"#include <stdio.h>int main(){mxArray *x_ptr;mxArray *y_ptr=NULL;double *y;double ret;/* Call the MCR and library initialization functions */if( !mclInitializeApplication(NULL,0) ){fprintf(stderr, "Could not initialize the application.\n");exit(1);}if (!foolibInitialize()){fprintf(stderr,"Could not initialize the library.\n");exit(1);}/* Create an mxArray to input into mlfFoo */x_ptr = mxCreateDoubleScalar(1);/* Call the implementation function *//* Note the second input argument should be &y_ptr instead of y_ptr*/mlfFoo(1,&y_ptr,x_ptr);/* The return value from mlfFoo is an mxArray so we must extract the data from it */y = mxGetPr(y_ptr);ret = *y;/* Print a double precision number*/printf("The output of foo is %f\n",ret);/* Call the library termination function */foolibTerminate();mxDestroyArray(x_ptr);mxDestroyArray(y_ptr);mclTerminateApplication();return 0;}
5. Select your project in the Solution Explorer. From Project menu option, select Properties. Open the Linker folder and select the General category. Add the location of foolib.lib and the following
$MATLABROOT\extern\lib\<arch>\microsoft\msvc71
in the Additional Library Directories field. Note $MATLABROOT is the MATLAB root directory on your machine, as returned by typing
matlabroot
at the MATLAB Command Prompt.
For example, you may have
c:\foo;$MATLABROOT\extern\lib\<arch>\microsoft\msvc71
in the Additional Library Directories field.
Note that for MATLAB releases starting with MATLAB 7.2 (R2006a), there are no subfolders under
$MATLABROOT\extern\lib\<arch>\microsoft
Therefore add this folder instead of
$MATLABROOT\extern\lib\<arch>\microsoft\msvc71
if you are using MATLAB 7.2 or later.
6.After specifying the library directories, select the Input category and type the following libraries in the Additional Dependencies field:
mclmcrrt.lib
foolib.lib
7. Open C/C++ folder, select General. Add to Additional Include directories field:
$MATLABROOT\extern\include
Also add to the Additional Include directories field the directory in which foolib.h is located.
8.Under C/C++ folder, select Code Generation. In the Runtime Library, select Multi-threaded DLL. Click OK.
9. Check the target machine flag in Visual Studio: This should correspond to the libraries that you are linking against. For example, if you specify ’x64’, it should link against the 64-bit MATLAB libraries. If you specify 'Win32', it should link against 32-bit MATLAB libraries.
For additional information on how the target platform of the Visual Studio project can be changed, refer to
"How to: Configure Visual C++ Projects to Target 64-Bit Platforms" at:
<http://msdn2.microsoft.com/en-us/library/9yb4317s(VS.80).aspx>
10. Go to Build->Build Solution. You should now have built test.exe.
Please make sure to choose 'x64' option from the drop down menu for the 'Solution Platform' window in Visual Studio before building your project if you are linking against '64 bit' libraries.After building the project, an additional folder named 'x64' will be created in your current project working directory and your executable will be placed in it.
11. Place foolib.dll in folder where test.exe is located, if you have changed the Visual Studio Platform to 64bit then your executable will be in a folder 'x64'.
12. Run your application.
NOTE: The <arch> folder mentioned above referred to "win32" or "win64" folder depending on whether you want to create a 32 bit or 64 bit C shared library respectively.
As of MATLAB 7.3 (R2006b) there is a toolbox called the MATLAB Builder for Java which is designed to provide a way to deploy MATLAB code which can be used from Java.
For older releases of MATLAB, Compiler-generated shared libraries may be called from a Java application by creating an intermediate shared library that forwards function calls to the Compiler-generated library. This intermediate library serves three purposes:
1. Provides the "glue" between the Java language and the native C/C++ code.
2. Converts input and output arguments between Java and MATLAB data types.
3. Handles errors occurring in MATLAB code so that they appear as Java exceptions.
The Java language provides a standard mechanism by which Java applications can access so-called "native" code written in C or C++. This interface, known as the Java Native Interface, or JNI, provides a language binding between Java and the intermediate C/C++ shared library, as well as an API for accessing data stored in Java arrays from this native code.
The basic procedure for integrating a Compiler-generated shared library into a Java application can be summarized in the following steps.
1. Create a shared library to expose the necessary MATLAB functions to C or C++ using the MATLAB Compiler. This step will create a shared library and an associated header file (.h) containing declarations of the exported functions in this library.
2. Create a Java file (.java) that contains a class with a set of native methods corresponding to the functions in the library created in step 1 that you wish to call from Java. Compile this file into a .class file.
3. Use the javah utility (see your Java documentation for information on how to use the javah utility) to create a header file (.h) containing the C/C++ to Java mapping of the native methods created in step 2.
4. Create a C or C++ file that includes the header files generated in steps 1 and 3 and provides implementations of the native Java methods. Each method implementation contains the necessary data conversion and error handling code, and calls the corresponding function in the Compiler-generated shared library.
5. Compile and link the file created in step 4 into a shared library. Link this library with the shared library created in step 1.
The following example illustrates the procedure for calling a MATLAB Compiler-generated shared library from Java. In this example, we will rewrite the C shared library example in the beginning of the section on shared libraries in the MATLAB Compiler documentation. The new version will be called from a Java main application instead of a C main application.
Compiling the shared library
1. Copy the following files from <matlabroot>/extern/examples/compiler to your work directory:
<matlabroot>/extern/examples/compiler/addmatrix.m <matlabroot>/extern/examples/compiler/multiplymatrix.m <matlabroot>/extern/examples/compiler/eigmatrix.m
where <matlabroot> denotes the directory into which MATLAB 7.1(R14SP3) is installed.
2. Execute the following at the MATLAB Command Prompt:
mbuild -setup
Once prompted, make sure you select a supported compiler (other than LCC if you are on a Windows machine). For information on supported compilers, refer to the following link:
Now use the following command at the MATLAB Command Prompt to build your shared library:
mcc -vB csharedlib:libmatrix addmatrix.m multiplymatrix.m eigmatrix.m
Writing the driver application
3. In this example the driver application is a Java application. This application contains the same basic steps as in the previous example's matrixdriver.c, except we now implement it in Java. This is called MatrixDriver.java and is attached to this solution. This simple Java class contains three main parts:
a. A list of native methods corresponding to the functions that we will need to call in our Compiler-generated shared library.
b. A main function that performs initialization and calls the functions.
c. A static block that loads the native library (jnimatrixdriver) that we will create to bridge this Java code with the Compiler-generated shared library.
Compiling the driver application
4. We compile this Java code using the Java compiler, javac. After compiling, we use the javah utility to generate a JNI header file by executing the following commands at the system prompt (the user is assumed to be familiar with the necessary Java tools. Refer to your Java Development Kit (JDK) documentation for more information):
javac MatrixDriver.java javah -jni MatrixDriver
Writing the intermediate JNI stub library
5. The intermediate JNI code in this example is written in C and resides in the file jnimatrixdriver.c, which is attached to this solution. This file contains the implementation of each native method listed in MatrixDriver.java. This file also includes the header file generated by javah (MatrixDriver.h), as well as the header file generated by the MATLAB Compiler (libmatrix.h). Each of the native methods implemented in this file follow a naming convention defined by the JNI specification and the prototypes of these functions are defined in MatrixDriver.h. For more information, refer to the JNI documentation for a complete discussion of this subject.
Compiling the JNI stub library
6. The final step in building our application is to compile the JNI stub library into a shared library that links against our MATLAB Compiler-generated shared library. Do this with mbuild as follows on Windows at the MATLAB Command Prompt:
mbuild -I<jdk-dir>\include -I<jdk-dir>\include\win32 jnimatrixdriver.c jnimatrixdriver.exports libmatrix.lib -link shared -output jnimatrixdriver
For UNIX, use:
mbuild -I<jdk-dir>/include -I<jdk-dir>/include/<arch> jnimatrixdriver.c jnimatrixdriver.exports -L. -lmatrix -link shared -output jnimatrixdriver
Here, <jdk-dir> represents the location of your JDK installation. The directories <jdk-dir>/include and <jdk-dir>/include/<arch> refer to the location of the JNI header files in your JDK installation, with <arch.> representing the platform-specific directory beneath <jdk-dir>/include. The value of <arch> will vary depending on which platform you are developing on (i.e., on Windows, <arch> = "win32"). Consult your JDK documentation for the location of these directories. The JNI include directories must be included in the mbuild command using the -I switch. In the mbuild command listed above we also pass an exports file, jnimatrixdriver.exports, which is simply an empty file. We do not need to explicitly list exported functions for this library because the declarations provided for us from javah take care of exporting the native methods.
7. Testing the driver application
Follow these steps to test the driver application:
a. Add the directory containing the shared libraries built in steps 1 and 6 listed above to your dynamic library path. If you are following the example, this will be your current working directory.
b. Run the application using the following command at the system prompt:
<matlabroot>\sys\java\jre\<arch>\<jre-dir>\bin\java <java-args> MatrixDriver
To run this application on a deployment machine, you will need to copy <matlabroot>\sys\java\jre\win32\jre1.5.0\bin\java.exe from your development machine to <mcrroot>\sys\java\jre\win32\jre1.5.0\bin, where <mcrroot> denotes the directory into which MATLAB Component Runtime 7.3 (R14SP3) was installed. You can then use the following command at the deployment machine's system prompt:
<mcrroot>\sys\java\jre\<arch>\bin\java <java-args> MatrixDriver
The java command is run with a set of command line options, denoted here as <java-args> that represent options to be passed onto the Java Virtual Machine (JVM) when it is initialized.
Before running the application, we should discuss how the MCR uses the JVM. The MCR embeds its own JVM that it uses to execute any Java code accessed by MATLAB code. When you initialize an MCR inside of an application that has already started its own JVM, the MCR will attach itself to the already-running JVM. This step is necessary because the Java runtime does not support the creation of more than one JVM at a time inside of a single process. Therefore, if your application uses MATLAB Java code or MATLAB graphics (which uses Java figures), you will need to use the same set of JVM initialization options that are used by the MCR internally, and it is strongly recommended that the JRE version is the same version as the one currently used by the MCR. The following table lists these properties for various platforms for the MCR version 7.3. It should be noted that this information is subject to change from release to release.
Platform JRE version JVM startup arguments
glnx86 1.5.0 -Xms64m -Xmx96m -XX:NewRatio=3 -XX:MaxPermSize=32M -ea -esa
hpux 1.4.1 -Xms64m -Xmx96m -XX:NewRatio=3 -XX:MaxPermSize=32M -ea -esa
win32 1.5.0 -Xss512k -Xms64m -Xmx96m -XX:NewRatio=3 -XX:MaxPermSize=32M -Dsun.java2d.noddraw=true -Dsun.awt.nopixfmt=true -ea -esa
mac 1.4.2_05 -Xms64m -Xmx96m -XX:NewRatio=3 -XX:MaxPermSize=32M -ea
sol2 1.5.0 -XX:ThreadStackSize=8100 -Xms64m -Xmx96m -XX:NewRatio=3 -XX:MaxPermSize=32M -ea -esa
glnxa64 1.4.2 -Xms64m -Xmx96m -XX:NewRatio=3 -XX:MaxPermSize=32M -ea -esa
For example, if we were to run this application on Windows, we would issue the following command:
<matlabroot>\sys\java\jre\win32\jre1.5.0\bin\java -Xss512k -Xms64m -Xmx96m -XX:NewRatio=3 -XX:MaxPermSize=32M -Dsun.java2d.noddraw=true -Dsun.awt.nopixfmt=true -ea -esa MatrixDriver
For purely numeric applications that do not use Java code called from MATLAB, This restriction is not necessary. In this case the application can be initialized with "-nojvm", which tells the MCR not to try to start a JVM or to attach to an existing one. This can be done by modifying the call to mclInitializeApplication in jnimatrixdriver.c as follows:
const char* ops = "-nojvm";mclInitializeApplication(&ops, 1);
Since the current example does not use graphics or any MATLAB based java calls, we could use this option here if necessary.
When the example is run, the following output should appear:
The value of added matrix is:
2.0 8.0 14.0 4.0 10.0 16.0 6.0 12.0 18.0
The value of the multiplied matrix is:
30.0 66.0 102.0 36.0 81.0 126.0 42.0 96.0 150.0
The Eigen value of the first matrix is:
16.116843969807054 0.0 0.0 -1.1168439698070436 0.0 0.0 2.6048391707365234E-18 0.0 0.0
For further information regarding JNI programming, refer to "The Java Native Interface Programmer's Guide and Specification" by Sheng Liang (published by Addison-Wesley).
Related Question
- How to create a C shared library with MATLAB Compiler 4.4 that can be used in a Microsoft Visual Studio 2005 win32 Console Application
- How to compile and run a MATLAB Engine program on UNIX/Linux/Mac
- How to create a C – shared library with MATLAB Compiler 3.0 which can be used in other projects
- Do I receive unresolved symbol errors when running a stand-alone application generated by MATLAB Compiler 4.0 (R14) on the HP-UX machine
- How to create a C shared library with MATLAB Compiler 4.0 (R14) that can be used in a Microsoft .NET 2003 project
- How to create a shared library which does not use a display with MATLAB Compiler
- Do I get an error when trying to run the MATLAB R2012b deployed application from the Mac Finder window
Best Answer