Wednesday, August 19, 2009

Interfacing Matlab and C/C++ using direct dll invocation

Suppose I have an algorithm the implementation of which if run from Matlab is going to take forever. Fortunately I got an implementation of this in c/c++ and would like to invoke this c++ code from Matlab. There are quite a few conventional ways of doing this.
1) invoking the c++ exe file from Matlab passing the right arguments. This is not very attractive since the exe has to be loaded everytime it is going to be used and I am planning to use it atleast a million times in experiment.

2) writing a mex function wrapper for over the c++ implementation and then call the function from matlab. I went quite far with this approach, but the farther I went, it looked lesser appealing due to the following points:
a) there are only a few compilers supported by matlab for building c/c++ files (using the mcc setup). I am using matlab 2006, and it has only lcc and microsoft visual studio without .net supported. I installed another Borland c++ lightweight compiler for the purpose, but the c++ syntax rules were a bit different in it from vc++ syntax and more over I had to convert my other library inclusions to borland omp format using coff2omp.exe utility. Overall it was a pain.
b) I needed to learn a lot of matlab memory allocation and deallocation apis to use the mex files. And I wanted a very fast way of coding this up.
c) The VC++ IDE was useless other than just for coding up my c++ code. It would be nicer if I could use the vc++ ide for building and debugging the code.

3) The above problems motivated me to look at the following very elegant solution, which is to build the c++ algorithm into a dll file and load the dll inside matlab, later calling the function directly.

Here are the steps to do this:
1) Write up your code in VC++ and build it to a dll.  (In case of Linux, you need to build the code to a shared library object using g++ -shared option).
a) You need to change the "configuration type" in the project properties to dll for this.
b) Also, you need to add a __declspec (dllexport) to the function you would like export to matlab. For ex:

__declspec (dllexport) double* MyMatlabFunction(char*, int*, int );

Place all such exports in a single header file, say functionexports.h (this will be required later).
c) Build the code and create a dll, (say mycode.dll) using vc++.

2) load the dll in matlab.
a) loadlibrary(), function in matlab loads a dll. the syntax is given below:
>loadlibrary('mycode', 'functionexports.h');
Note that you need to pass in the dll name and the headerfile referred above to the loadlibrary call. You can check if the library is already loaded using the "libisloaded('mycode.dll')" call and use unloadlibrary('mycode.dll'); to unload a library (which might be needed if you want to rebuild your dll from vc++).

b) Once the dll is loaded, use the calllib() function to invoke the exported dll function. The syntax is as follows:
[outargs]=calllib('libname', 'funname', inargs);
ex: [dptr]= calllib('mycode', 'MyMatlabFunction', 'somestring', x, y);
Thats it.

c) a little tricky part here is to operate on the arguments to and from the function. A good tutorial on how to do this is given in the link here .

A simple example that calls a c++ function that takes three arguments; a string, an integer pointer and an integer, and returning a double pointer is given below:
Matlab call Example:
function [sift, n]=ComputeSift(imgfilename, disp)
tic;
if ~libisloaded('siftlight')
loadlibrary('siftlight', 'siftlight.h');
end

sift=0; n=0;
nptr=libpointer('int32Ptr', n);
siftptr=calllib('siftlight', 'mysift', imgfilename, fptr, disp);

if fptr.Value > 0
setdatatype(siftptr, 'doublePtr', 128, fptr.Value);
sift=siftptr.Value;
n=fptr.Value;
end

t=toc;
fprintf('sift took %f seconds...\n', t);
end

The solution is fast and elegant, you can use the whole power of VC++ for building and debugging, and there is very less to learn (you should just know how to pass in and take back arguments from the call). Hope this information is helpful.