DIPimage User Manual » Writing MEX-files that use DIPlib

A MEX-file is a compiled C, C++ or Fortran function (C++ if it uses DIPlib) that can be called from MATLAB as if it were a normal MATLAB function. It must take MATLAB data as input and produce MATLAB data as output. To call a DIPlib function from the MEX-file, the MATLAB data must be converted to the right C++ types. This chapter describes the functionality we wrote for this purpose.

It is assumed that the reader is familiar with basic MEX-files (see the MATLAB MEX-file documentation if not) and basic DIPlib (see the documentation if not). We exclusively use the C API.

The DIPlib–MATLAB interface

The header file dip_matlab_interface.h contains a series of functions that can be used to convert MATLAB types to DIPlib types and vice versa. These functions make it very easy to write a MATLAB interface to DIPlib functions (and this is its main purpose), but could be used for other purposes too.

All its functionality is in the dml namespace.

Output images

The main trick that it can do is prepare a dip::Image object that, when forged by a DIPlib function, will have MATLAB allocate the memory for the pixels, such that no copy needs to be made when this image is returned to MATLAB. For this, create an object of type dml::MatlabInterface. Its dml::MatlabInterface::NewImage function creates a raw image that can be forged (or passed as output image to any DIPlib function). The dml::GetArray function can then be used to obtain a pointer to the mxArray containing a dip_image object with the same pixel data. Note that the dml::MatlabInterface object needs to exist throughout this process, as it owns the data until dml::GetArray extracts it.

This is a skeleton MEX-file that outputs such an image:

#include <dip_matlab_interface.h> // Always include this, it includes diplib.h and mex.h

void mexFunction( int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] ) {
   try {

      // Create an output image
      dml::MatlabInterface mi;
      dip::Image out = mi.NewImage();

      // Forge it
      out.ReForge( { 256, 256 }, 1, dip::DT_UINT8 );
      out.Fill( 0 ); // Usually you'd do something more exciting here!

      // Retrieve the MATLAB array for the output image (it's a dip_image object)
      plhs[ 0 ] = dml::GetArray( out );

   } DML_CATCH
}

The documentation to dml::MatlabInterface gives more details about how to use the images created in this way.

Input images

The function dml::GetImage takes an mxArray pointer, checks it for validity, and returns a dip::Image object that shares data with the mxArray (except in exceptional circumstances: complex-valued numeric arrays must be copied because their storage is different in MATLAB and DIPlib; complex-valued dip_image objects are not copied).

For example, one can add the following line to the mexFunction above:

dip::Image const in = ( nrhs > 0 ) ? dml::GetImage( prhs[ 0 ] ) : dip::Image();

This line calls dml::GetImage only if prhs[0] actually exists. If not, it creates a raw image object. You should always check nrhs before reading any of the prhs elements. Likewise, you should always check nlhs before assigning to any of the plhs elements except the first one (plhs always has at least one element, even if nlhs == 0).

Converting other types

There exist similar Get... functions for just about every DIPlib type, for example dml::GetFloat, dml::GetFloatArray or dml::GetFloatCoordinateArray. See the documentation to the dml namespace for a complete list. These take an mxArray pointer as input, validate it, and output a value of the appropriate type. If the validation fails, an exception is thrown.

There exist also a series of dml::GetArray functions that do the reverse process: they take a value of any type typically returned by a DIPlib function, and convert it to an mxArray, returning its pointer. Note that MATLAB always takes care of freeing any mxArray objects created by the MEX-file, there is no need to do any manual memory management.

These data conversion functions all copy the data (only images are passed without copy, other data is typically not large enough to matter).

For more complex examples of MEX-files, see examples/external_interfaces/matlab_mex_example.cpp, as well as the DIPimage MEX-files in dipimage/private/ and dipimage/@dip_image/private.

Compiling a MEX-file

To compile a MEX-file like the one shown in the previous section, save it for example as myfunction.cpp, and use the dipmex function in MATLAB:

dipmex myfunction.cpp

This function simply calls the mex function, adding arguments to allow the compiler to find the DIPlib header files and to link in the DIPlib library. Because this is C++, it is important that the same compiler (and often also the same version) be used to build the MEX-file as was used to build the DIPlib library. We recommend that you build the library yourself. mex -setup C++ should be used to configure MATLAB’s mex command to use the right compiler.

The result of the dipmex command above is a MEX-file called myfunction. You can call it like any other MATLAB function:

img = myfunction;  % it has no input arguments

If your MEX-file needs more source files and/or libraries, simply add them to the dipmex command. You can also add other arguments for mex here:

dipmex myfunction.cpp other_source.cpp /home/me/mylibs/libstuff.a -I/home/me/mylibs/

The MEX-file will always have as name the name of the first source file in the list, unless an -output mexname argument is given.