« Previous « Start » Next »

7  Calling TOMLAB from C/C++

This section describes how to create a standalone shared library with TOMLAB functionality using the MCC compiler.

The guide covers MCC 3 as well as MCC 4. If using MCC 3, make sure to patch it to R13SP1.

7.1  Creating a stand alone shared library

The procedure to create a standalone shared library of TOMLAB files is identical to creating a standalone application, except for the commands to compile and link the files. As described earlier, copy all needed m-files and mex-files to a single directory. If needed, create new m-files as an interface between TOMLAB and C/C++. These can be used as entry points to the shared library (although, all m-files can be used as entry points).

A suitable entry point could be an m-file taking F, c, A, b_L, b_U, x_L and x_U matrices as input, generating a QP Prob struct out of this, and calling a suitable solver. Only the results of interest, for example the optimal vector x and objective function value, could be returned.

After all MATLAB files have been put in a single directory, compile them into a shared library using the following command:
> mcc -B csharedlib:<lib-name> <m-files> <mex-files>
This creates a shared library: <lib-name> with extension depending on platform (.dll on Windows, .so on Linux).

If the client to use the shared library is written in C++ one can build a C++ shared library supporting exception handling and C++ classes for handling the MATLAB arrays. The command to compile a C++ shared library is:
> mcc -B cpplib:<library name> <m-files> <mex-files>
For more detailed information about this, refer to:

7.2  Calling the shared library from C/C++

The new shared library now contains entry points for all files compiled with MCC; mex-files as well as m-files. Each m-file has two library functions that may call it:
Notice that the first character in the function name is always upper case. The rest of the characters are always lower case, regardless of the case of the original function.

The difference between the two functions prefixed with mlx and mlf is the way the arguments are passed. The mlx-function expects the arguments like this:
extern void mlxSolveqp(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);
just like a mex-file (Refer to the MATLAB documentation for more details and information on this.)

The mlf-function is perhaps more user friendly, as it looks more like the original function call in MATLAB. Observe that the arguments to the mlf-functions differ between MCC 3 and MCC 4.

The MATLAB function:
function [x, f] = solveqp(F, c, A, b_L, b_U, x_L, x_U)
is declared in the standalone library as follows when using MCC 4:
extern void mlfSolveqp(int nargout, mxArray** x, mxArray** f, mxArray* F
                       , mxArray* c, mxArray* A, mxArray* b_L
                       , mxArray* b_U, mxArray* x_L, mxArray* x_U);
A MATLAB function without left hand side arguments do not have the nargout and pointer to pointer arguments.

The same MATLAB function is declared like this when using MCC 3:
extern mxArray * mlfSolveqp(mxArray * * f,
                            mxArray * F,
                            mxArray * c,
                            mxArray * A,
                            mxArray * b_L,
                            mxArray * b_U,
                            mxArray * x_L,
                            mxArray * x_U);
The return value is the first left hand side parameter; the MATLAB x in this case.

In order to call these function in the shared library from a client application, there are some tasks that must be completed before anything else. First of all, one has to include a header file in the application generated by the MCC compiler when compiling the library. The name of the file is the name of the library plus the extension .h. Each time the shared library is recompiled a new header file will be generated. This header file includes all necessary function declarations needed when calling a shared library, setting up input data and reading output data. No other header files need to be included in order to use the shared library.

Before using any of the MATLAB API functions, a function mclInitializeApplication() has to be called. This only applies to MCC 4 though. In MCC 3 there is no mclInitializeApplication()-function.

Before calling any of the functions in the shared library, an initialization function has to be called. The name of this function is: <lib-name>Initialize(), where <lib-name> is the name of the library (including the lib prefix on Linux).

When these two (or one in MCC 3) functions have been called, all m- and mex-files are callable from within the application using the prefixes mlf or mlx. At this point the application could for example read measurement data from a device or read input data from a user interface, then formulate an optimization problem and call TOMLAB through the shared library. It is recommended to write m-files for compilation with the shared library to act as an interface between the application and TOMLAB as it is usually easier to handle MATLAB data in the MATLAB language than in C.

When all calls to the shared library are done, a termination function should be called: <lib-name>Terminate() where <lib-name> is the name of the library (including the lib prefix on Linux).

When the MATLAB API functions are not needed anymore, call mclTerminateApplication(). This only applies to MCC 4.

To compile the application, use the mbuild utility:

On Windows:
> mbuild <source code files> <lib-name>.lib
where <source code files> are the source code files for the application, and <lib-name> is the name of the shared library generated by MCC earlier.

On Linux:
> mbuild <source code files> -l<lib-name> -L. -I.
where <source code files> are the source code files for the application, and <lib-name> is the shared library generated by MCC earlier without the lib-prefix and without the extension.

7.3  TOMLAB /CPLEX QP solver example

The TOMLAB distribution includes an example running TOMLAB /CPLEX for a QP problem from a separate C application. It is available in the TOMLAB distribution in the /examples/sal/sallib directory.

In summary, the example was constructed like this:
  1. An m-file called solveqp.m was created to take simple input in the form of matrices for F, c, A, b_L, b_U, x_L and x_U. This m-file creates a QP Prob structure from these matrices and runs the TOMLAB /CPLEX solver through tomRun and returns the optimal vector x and objective function value.

  2. The profiler in MATLAB was turned on and the solveqp function was called with some QP data. When a solution was obtained, the profile report command displayed the m- and mex-files used during the execution.

  3. The files were copied to a project directory for the new shared library.

  4. In xnargin.m, some changes were made in order to have more descriptive error messages when failing to find a specific function. See xnargin.m for instructions on what to change.

  5. The library was built using the MCC compiler. (See the make file for the example for details).

  6. A simple client application was written creating input data for the solveqp.m function, calling it and writing the results to the screen. (See the Appendix A for example code).

  7. The application was built using the mbuild command. (See the make file of the example for details).

  8. The application was run, and there were some error messages reporting missing files.

  9. The missing files were added to the command building the library, and the library was rebuilt.

  10. Step 8 and 9 were repeated a few of times until everything was working smoothly.
Source files for the simple client application (application.c) and the interface m-file (solveqp.m) are available in Appendix A of this document.

« Previous « Start » Next »