Converting a C++ library into MATLAB mex - c++

I have a big C++ code and I want to integrate this into MATLAB so that I can use it inside my matlab code. If it was a single code making its mex file would have been the best option. But since now it's a code that needs to be compiled and built in order to run, I don't know how can I use the functions in this code.
Is making mex files for the whole code the only option or is there any other workaround? Also I would like some help on how can I make mex files for the whole code and then build it.
For more insight, this is the code I am trying to integrate in matlab http://graphics.stanford.edu/projects/drf/densecrf_v_2_2.zip . Thank You!

First you'll need to compile the library (either static or dynamically linked). Here are the steps I took on my Windows machine (I have Visual Studio 2013 as C++ compiler):
Generate Visual Studio project files using CMake as described in the README file.
start VS, and compile densecrf.sln solution file. This will produce a static library densecrf.lib
Next modify the example file dense_inference.cpp to make it a MEX-function. We'll replace the main function with:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
..
}
and instead of receiving arguments in argc/argv, we'll obtain the parameters from the input mxArray. So something like:
if (nrhs<3 || nlhs>0)
mexErrMsgIdAndTxt("mex:error", "Wrong number of arguments");
if (!mxIsChar(prhs[0]) || !mxIsChar(prhs[1]) || !mxIsChar(prhs[2]))
mexErrMsgIdAndTxt("mex:error", "Expects string arguments");
char *filename = mxArrayToString(prhs[0]);
unsigned char * im = readPPM(filename, W, H );
mxFree(filename);
//... same for the other input arguments
// The example receives three arguments: input image, annotation image,
// and output image, all specified as image file names.
// also replace all error message and "return" exit points
// by using "mexErrMsgIdAndTxt" to indicate an error
Finally, we compile the modified MEX-file (place the compiled LIB in the same example folder):
>> mex -largeArrayDims dense_inference.cpp util.cpp -I. -I../include densecrf.lib
Now we call the MEX-function from inside MATLAB:
>> dense_inference im1.ppm anno1.ppm out.ppm
The resulting segmented image:

An alternative approach can be to compile your large C++ code into a shared library (.dll or .so depending on your OS) and then load this library in Matlab using loadlibrary.
Once the library is loaded you can call each and every one of its API functions using calllib.
Example: assuming you are working in Linux environment and you have you c++ code in a file myLib.cpp with a header file myLib.h, then you can use g++ to create a shared library
$ g++ -fPic -c myLib.cpp
$ g++ -shared -o myLib.so myLib.o
Now, in Matlab, you can load the library (assuming the .so file and .h files are in your matlab path)
>> loadlibrary( 'myLib', 'myLib.h' );

Related

How can I link to DLLs from a C++ program built under Cygwin?

Given the following files
RsbbDec.exe
Run_RsbbDec.exe
TRSCompress.dll
TRSCompress.lib
and the following example code:
#include <iostream>
#pragma comment(lib, "TRSCompress.lib.")
extern "C" __declspec(dllexport) int Run_RsbbDec(const char* Input_File, int vbr_en, int bitrate , char *ErrMsg);
#define TEXTLEN 1024
int main()
{
char ErrMsg[TEXTLEN];
if(Run_RsbbDec("audio.pcm", 1, 1, ErrMsg))
{
std::cout <<"ok";
}
else
{
std::cout <<"error";
}
}
How do I make the sample code work? The only instruction I was given was to make sure that the .dll and the 2 exes are in the same directory.
It seems to me that the main point of the demo code is to run the Run_RsbbDec function which I think is located in one of the executables.
I get a linker error when I run the code:
/tmp/ccuvBnWV.o:main.cpp:(.text+0x2b): undefined reference to `Run_RsbbDec'
I am using this command to compile:
g++ main.c RsbbDec.exe Run_RsbbDec.exe
Likely, the third-party supplied DLL was not built under Cygwin, but natively with Visual Studio (or similar).
That's okay, but you have to do some more work to form a compatibility between the two different environments.
You can read about it on the Cygwin website's page "Building and Using DLLs":
If you have an existing DLL already, you need to build a Cygwin-compatible import library. If you have the source to compile the DLL, see the section called “Building DLLs” for details on having gcc build one for you. If you do not have the source or a supplied working import library, you can get most of the way by creating a .def file with these commands (you might need to do this in bash for the quoting to work correctly):
echo EXPORTS > foo.def
nm foo.dll | grep ' T _' | sed 's/.* T _//' >> foo.def
Note that this will only work if the DLL is not stripped. Otherwise you will get an error message: "No symbols in foo.dll".
Once you have the .def file, you can create an import library from it like this:
dlltool --def foo.def --dllname foo.dll --output-lib foo.a
Alternatively, use native tools to build your own program.
Also, the pragma is wrong; there's an errant period at the end of the filename.

JNI and shared library

Trying to create dll.
So first I created a .java file as follows:
class Main
{
static
{
System.loadLibrary("sample_dll");
}
static native void sritest();
public static void main(String [] a)
{
sritest();
}
}
Then I compile it with no error to .class.
Then using javah I created Main.h.
Then I write following code in c++.
#include <jni.h>
#include <Main.h>
JNIEXPORT void JNICALL Java_Main_sritest(JNIEnv *env,jobject obj)
{
printf("hi");
}
Then I compiled this using MinGw by the following code
g++ -c sample_dll.cpp
g++ -shared -o sample_dll.dll sample_dll.o
Then I place this in java library path.
Then I run Main.java but the following exception occurs
Unstatisfied link error; sritest ()V
I find an answer . It is i do three mistakes. When compiling with c++ we must declare my jni function in extern "C"{} block. Second when compiling in minGW compiler we should use following code and implement include folder of jdk . The code now worked and my program runs smoothly without problem in jni.
The command line code for compiling .o to .dll code is after creating sample_dll.o we must do
g++ -Wall -D_JNI_IMPLEMENTATION -Wl,--kill-at -Ic:/path_of_include_folder_in_jdk_without_drive_letter -Ic:/path_of_win32_folder_in_include_folder_in_jdk_without_drive_letter -shared -o sample_dll.dll sample_dll.o
The last mistake is i want to include Main.h compiled by javah utlity that created from my java code.
This is done by
Javac Main.java
Javah Main
Then take the header file Main.h created and place it in the c++ compiler's include folder. That in my computer c:\minGW\include .
In c++ code add additional preprocessor
#include<Main.h>
All done create dll and place it in one of default java library path . The paths can be getted by using the following function in java
System.out.println (System.getProperty ("java.library.path"));

How to load a .o file at runtime in C++?

I'm writing a plugin library in C++ and need to call a remote function which is not defined (only declared) at the time of compilation of the host program.
I need the host program to call a function in plugin program but I also need the flexibility of compiling host program at one time and plugin program later and get the host to run a remote function from plugin.
Here's a basic implementation of my solution:
I made these 3 files:
host.cpp:
#include "plug.h"
int main() {
cout<<"Hello World!"<<endl;
remoteFunction();
return 0;
}
plug.cpp:
#include "plug.h"
void remoteFunction() {
cout<<"in Remote"<<endl;
return;
}
plug.h:
void remoteFunction(void);
Then I compiled plug.cpp using g++ -c plug.cpp to generate plug.o.
Now I can use g++ host.cpp -o executable plug.o to get a single executable file which runs fine. But this way I need to fully define the remote function beforehand. How do I get host.cpp to compile without compiling plug.cpp first.
If there are some completely different ways to get this functionality, suggestions are most welcome.

How to create a C++ library in Eclipse?

Here a person asks "How to make your own library in C++ ?". This is exactly the question that I have. There is an answer to this question:
Create the files "mylibrary.h" and "mylibrary.cpp".
Only compile the library, and it shouldn't have a "main()" function in
it. This step will generate an object file called "myfile.o".
Create another file called something like "main.cpp". In main.cpp
you need to #include "mylibrary.h".
Compile main.cpp and add the library from step 2 to link in (in this case "myfile.o"). If you don't add this library, you'll get a
error message like "linker error - can't find function definition", or
something like that.
But I still have some questions:
The Library.cpp should have a main() function. But what should be in this main function? I do not want my library to execute something by default, when my program starts. I want it to contain a set of functions that are executed only when they are called explicitly.
In the step 4, it is written that I need to "Compile main.cpp and add the library from step 2", but I have already compiled the library on the step 2. Should I compile it one more time?
What does "in this case 'myfile.o'" mean? What exactly should I do with "myfile.o" in this case?
On the step 4 it is written "If you don't add this library, you'll get a error message". But what does "to add library" mean? On step 3 I put #include "mylibrary.h" into the main.cpp, so I have added the library? Or I need to do something more to add the library?
Could you please help me to understand the answer?
ADDED: I think I need to use Eclipse to generate .a, .lib, .so, or .dll files? Does anyone know how I can do it and what exactly I should generate?
For this example, consider a "library" which provides the factorial function. For simplicity, I use free functions.
// factorial.h
int factorial(int input);
// factorial.cpp
#include "factorial.h"
int factorial(int input) {
if(input > 0) return input * factorial(input - 1);
else if(input == 0) return 1;
else return 0;
}
Now compile these files to generate a factorial.o, but do not link. (Configure the Eclipse build command accordingly. If using gcc, use the -c and -o flags appropriately. Refer compiler documentation to understand what these flags do.)
Next create a main.cpp (you can actually name it anything you like.)
// main.cpp
#include "factorial.h"
int main() {
// use your library code here to make sure it is usable and working.
factorial(3);
factorial(5);
// etc.
}
Now compile this to a main.o, then link this together with the factorial.o from earlier to generate the executable. You can actually skip the intermediate main.o step, and do both of this in one step with the appropriate compiler options.

typeid of enum changing when dynamically linked in matlab mex file

I have a C++ library with a particular function that returns a boost::any, whose value type is a particular enum defined in a different included library. This normally works fine.
But when I link to my library dynamically from a Matlab mex file, typeid(the_enum_t) seems to be different for the things made in my library and those made in the caller, in that it doesn't compare ==. Since I'm actually using flann, whose version of boost::any performs a check based on type_info::==, this makes everything break. Static linking works fine, but that's kind of a pain here, and I'd really rather have it work either way.
I thought type_info::== was supposed to work consistently across library boundaries. Does this have to do with how Matlab dynamically loads libraries from mex?
Here's some code to reproduce this (also available in easy-to-download form, with a makefile, in this gist).
First, a stand-in for the library that defines the enum (flann):
namespace library {
enum the_enum_t { el_one, el_two, el_three };
}
Now a proxy for my library, stubby.hpp:
#include <boost/any.hpp>
#include "the_enum.hpp"
boost::any the_function();
And its implementation stubby.cpp:
#include "stubby.hpp"
boost::any the_function() {
return boost::any(library::el_two);
}
Finally, test code test.cpp, which is compiled with -DNO_MEX for a standalone and not for a mex file:
#include "stubby.hpp"
#include <boost/any.hpp>
#ifdef NO_MEX
#include <cstdio>
using std::printf;
int main() {
#else
#include "mex.h"
void mexFunction(int nlhs, mxArray **plhs, int nrhs, const mxArray **prsh) {
#endif
boost::any val_any = the_function();
printf("%s (equal: %d)\n",
val_any.type().name(),
val_any.type() == typeid(library::the_enum_t));
}
I get the expected output
N5flann17flann_algorithm_tE (equal: 1)
from each of
$ g++ -o test{,.cpp} -DNO_MEX libstubby.a && ./test
$ g++ -o test{_s,.cpp} -DNO_MEX libstubby.so && ./test_s
$ ln -sf test{,_s}.cpp && mex test_s.cpp libstubby.a && matlab -r test
But dynamically linking a mex file doesn't work:
$ mex test.cpp libstubby.so && matlab -r test
N5flann17flann_algorithm_tE (equal: 0)
I see this same behavior on
Matlab R2011b and R2011a, OSX 10.7, Apple gcc 4.2.1
Matlab R2011b, CentOS 5.7, gcc 4.1.2
Matlab R2010a, Ubuntu 11.04, gcc 4.4.5
The weird thing is that I could've sworn it worked a few months ago, but maybe I just did a bad job of testing.
Obviously I can get around this by static linking. But why is this happening? Does it have something to do with the way Matlab loads mex files and their libraries?
Boost has a workaround for this issue; see https://svn.boost.org/trac/boost/ticket/754
It's possible that boost is failing to enable the workaround. Try passing compiler flag -DBOOST_AUX_ANY_TYPE_ID_NAME per the patch on that ticket.