typeid of enum changing when dynamically linked in matlab mex file - c++

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.

Related

"undefined reference to `WinMain#16'" Error in gcc editor

I am just learning c++ and began to watch a youtube tutorial by thenewboston. Unfortunately he is using Code::Blocks while I am using gcc and I do not have the option to create new class files with a button click and so had to manually create them.
I dont understand why the same code in Code::Blocks and gcc will work in Code::Blocks but not gcc. Does gcc require different coding for the same language?
EDIT: I have downloaded and tested in Code::Blocks myself
Other questions talk of how I need to give windows an entry point, but I dont know how to do that.
Test.cpp Code:
#include <iostream>
#include "ClassTest.h"
using namespace std;
int main() {
ClassTest bo;
}
ClassTest.h Code:
#ifndef CLASSTEST_H
#define CLASSTEST_H
class ClassTest {
public:
ClassTest();
};
#endif // CLASSTEST_H
ClassTest.cpp Code:
#include <iostream>
#include "ClassTest.h"
using namespace std;
ClassTest::ClassTest() {
cout << "blah blah" << endl;
}
I'm not quite sure I understand what the question is; I'm going to take it as "how do I get these three files to build into a .exe that I can run from the Windows commmand line?"
The answer is to run something like this on the command line, in the folder with the files:
g++ -c Test.cpp -o Test.o
g++ -c ClassTest.cpp -o ClassTest.o
g++ Test.o ClassTest.o -o Test.exe
The first two commands build each CPP file into an "object file", which isn't a whole program by itself but which contains the compiled version of the code in that CPP file. The last command tells the compiler to paste together the two object files into a program, and resolve all the cross-references between them. (For example, the part where Test.cpp constructs a ClassTest object needs to end up calling the ClassTest constructor code from ClassTest.cpp.)
Code::Blocks is an IDE and works out how to build each source file in your project and link them together by itself. But if you aren't using an IDE, you need to do that in another way. You can either do it manually like this, or you can write a Makefile that will check which code files have changed and rebuild and re-link everything that depends on them when you run the make command, which is how most people do it.
As for "giving Windows an entry point", that probably refers to GUI applications that want to display windows on the screen. For console programs like the one you have written, the "entry point" is main(), and you just print stuff to the command line window. To make actual Windows-style GUI windows of your own, you need to use the Windows API, which I can't tell you much about.

GCC C/C++ MEX Matlab R2015 Mac OS X (with OpenMP) doesn't work

I'm trying to compile a very simple MEX file in Matlab using GCC/G++...
First I checked that this is already installed in matlab by:
!which gcc
output:
/usr/bin/gcc ...
After, I tried to do the following:
mex -v GCC='/usr/bin/gcc' hello.c
but it stills compiling with XCode Clang...
This is to use G++ with OPENMP library for parallel computing.
Is known that is NOT OFFICIALLY Supported by Mathworks, but POSSIBLE.
MATLAB only supports XCode 5.1+ or 6.0 on Mac.
See this list of supported compilers, from Mathworks:
Supported Compilers and Compatible Compilers - Release R2015a
EDIT!!!
Even Windows doesn't support a GCC compiler. However, if you can build your library in Windows there is a 3rd party library called Gnumex designed to provide MinGW or CygWin GCC compiler capabilities for Matlab MEX. Take a look.
An update on their website says that changed to Matlab have broken their utility. However, there seems to be a workaround available via this StackOverflow post.
Finally, I found a proper way to solve it...
First, the file mexopts.sh doesn't appear in the folder by default, is necessary to open a terminal and look for it and create it (then Matlab will redirect to it automatically when compiling with MEX):
find ~/ -name 'mexopts.sh'
and will appear:
/Users/FOO//.Trash/MATLAB_R2014a.app/bin/mexopts.sh
Then, copy it as:
cp /Users/FOO//.Trash/MATLAB_R2014a.app/bin/mexopts.sh ~/.matlab/R2014a
then go to the folder cd ~/.matlab/R2014a
and change permissions for your user as:
chmod u+rwx mexopts.sh
then, open it with your default text editor (Sublime text recommended) as:
open mexopts.sh
and edit the following:
Change where appears macosx10.7 to your current version, in my case macos10.10
then, modify the following lines as describen in (http://www.mathworks.com/matlabcentral/newsreader/view_thread/334250):
# CC='xcrun -sdk macosx10.7 clang' #OLD
CC='xcrun /usr/local/bin/gcc' #NEW
# CXX='xcrun -sdk macosx10.7 clang++' #OLD
CXX='xcrun /usr/local/bin/g++' #NEW
# CLIBS="$CLIBS -lstdc++" #OLD
CLIBS="$CLIBS -lstdc++ -I/usr/local/lib -lgomp" #directory <-I/usr/local/lib> #NEW
#CXXLIBS="$MLIBS -lstdc++" #OLD
CXXLIBS="$MLIBS -lstdc++ -I/usr/local/lib -lgomp" #NEW
IMPORTANT NOTE:
Make sure that your current G++/G++4.9 is able to compile with OpenMP, trying to include <omp.h> in a hello world file doing in the command line:
g++-4.9 -o test hello.cpp -fopenmp
or
g++ -o test hello.cpp -fopenmp
is also possible that a file is corrupted and is necessary to do Can not compile fortran because dyld: Library not loaded :
brew rm cloog
brew install cloog
(But check first)...
Is also possible that if you're not able to compile with OMP is necessary to do first a couple of things as described here (Compile OpenMP programs with gcc compiler on OS X Yosemite):
1. Got a new gcc complier from http://hpc.sourceforge.net/
2. Place a new executable folder by $ sudo tar -xvf gcc-4.9-bin.tar -C /
3. Switched to it by export PATH=/usr/local/bin:$PATH
Finally, try to compile your MEX file with:
mex hello.cpp COMPFLAGS="/openmp $COMPFLAGS"
That's it
... .
I was unable to get the mexopts.sh approach to work.
Instead I followed this first to make sure that I could get omp to work with xcode: clang-omp in Xcode under El Capitan
Then the mex compile st
mex CC='/usr/local/bin/clang-omp' -I/usr/local/include -I/usr/local/lib /usr/local/lib/libiomp5.dylib test.c
However, I get some weird results when comparing between Matlab and pure terminal based c. The common work, I put in the file "do_work.c":
double do_work(int maxit){
double tmp,x,x2;
int numThreads=0;
numThreads = omp_get_max_threads() ;
// numThreads = 4;
printf("Setting max num threads to %d.\n",numThreads);
omp_set_num_threads(numThreads);
// int Nthreads=omp_get_num_threads();
tmp = 0.0;
x2 = 0.0;
#pragma omp parallel for shared(tmp,x2) private(x)
for (int i=0;i<maxit;i++) {
x = 0.0;
for (int k=0; k<10000; k++) x += pow(.011,1.0/.5); // does some heavy computations
tmp += (double) i ;
if (i%1000==0){
printf("Hello, %d\n",i);
}
x2 += x;
}
printf("x2 = %f\n",x2);
return tmp;
}
I can compile this from command line using this wrapper file:
#include "stdio.h"
#include "math.h"
#include <libiomp/omp.h>
#include "do_work.c"
double do_work(int maxit);
int main(int argc, const char * argv[]) {
do_work(10000);
return 0;
}
I compile it by running
clang-omp -fopenmp test_c_wrapper.c
I can also interface to it from Matlab with this code:
#include "mex.h"
#include <libiomp/omp.h>
#include "math.h"
#include "stdio.h"
#include "do_work.c"
double do_work(int maxit);
void mexFunction(int nlhs, mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
do_work(10000);
return;
}
To compile this from Matlab, save it as test.c and run the first mex statement that I mentioned higher up. However, the results are really strange. It looks as if Matlab is not even using omp. At the same time, Matlab actually runs faster than the terminal based one, even though Matlab appears to run in serial mode? Strange... Also, the omp_get_max_threads() is acting weird, it doesn't return the same number every time when called from Matlab even though it does from terminal.

Converting a C++ library into MATLAB mex

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' );

Python importing & using cdll (with a linux .so file)

After one of my last questions about python&c++ integration i was told to use dlls at windows.
(Previous question)
That worked ok doing:
cl /LD A.cpp B.cpp C.pp
in windows enviroment, after setting the include path for boost, cryptopp sources and cryptopp libraries.
Now i'm tryting to do the same in linux, creating a .so file to import through ctypes on python2.5.
I did:
gcc -Wall -Wextra -pedantic A.cpp B.cpp C.cpp /usr/lib/libcryptopp.so -shared -o /test/decoding.so
and the so object is created ok. If removed "-shared" compilation is OK but stops as no main in there (obviously ;) ). Of course libcryptopp.so exists too.
But when i go to python and import the "so" file, it said that the attribute has no object "decrypt", "encrypt" or whatever i put there. using "dir" over the dll objects confirms that they are not there.
external functions are defined in A.cpp as:
int encrypt (params...)
//..
return num;
int decrypt (params...)
//..
return num;
also tried using:
extern "C" encrypt (params...)
.....
Could anyone tell me what i'm doing wrong?
Thanks in advance!
Rag
C++ compiler mangles names of functions. To do what you are trying to do you must have the declaration prototype inside
extern "C" {...}
it's hard to tell from your samples what exactly you have in a source file.
As someone already mentioned, use nm utility to see what objects that are in your shared object.
Do not compile your object without -shared. Python load library does not support statically linked objects as far as am aware.
compile your object with g++ compiler instead, it will link to standard C++ Library, gcc does not.
just to doublecheck something since you using boost.
#include <string>
#include <boost/python.hpp>
using namespace std;
string hello(string s){
return "Hello World!";
}
BOOST_PYTHON_MODULE(pyhello){
using namespace boost::python;
def("hello", hello);
}
in python
>>> import pyhello
>>> print pyhello.hello()
Hello World!
just my 2 cents, sorry if this couldn't help you.

boost::regex segfaults when using capture

I get a seg fault for the simple program below. It seems to be related to the destructor match_results.
#include <iostream>
#include <vector>
#include <string>
#include <boost/regex.hpp>
using namespace std;
int main(int argc, char *argv)
{
boost::regex re;
boost::cmatch matches;
boost::regex_match("abc", matches, re.assign("(a)bc"));
return 0;
}
edit: I am using boost 1.39
boost::regex is one of the few components of boost that doesn't exist solely in header files...there is a library module.
It is likely that the library you are using was built with different settings than your application.
Edit: Found an example scenario with this known boost bug, where boost must be built with the same -malign-double flag as your application.
This is one of several possible scenarios where your boost library will not have binary compatibility with your application.
Which version of boost are you using?
I compiled the above example with boost 1.36 and I don't get any seg faults.
If you have multiple boost libraries make sure that at runtime you're picking up the correct version.
Boost regex requires to be compiled against library -lboost_regex-gcc_whatever-is-your- version
In my case:
g++ -c -Wall -I /include/boost-1_36_0 -o main.o main.cpp
g++ -Wall -I /include/boost-1_36_0 -L/lib/boost-1_36_0 -lboost_regex-gcc33-mt main.o -o x
to execute:
LD_LIBRARY_PATH=/lib/boost-1_36_0 ./x
You would point to the location of boost include/libs on your system, note the version of gcc and m(ulti) t(hreaded) in library name - it depends on what you have compiled, just look in your boost lib directory and pick one version of regex library from there.
You are using temporary variable from which you want to obtain matches. I think, that your problem will resolved, if instead "abc" you will use following:
string a("abc);
regex_match(a, matches, re.assign("(a)bc"));
I was having the same problem. I tried the solution posted by Drew Dormann, but it didn't work. Then I discovered that I was actually linking against 1.40, but for some reason the headers were for 1.37. Once I downloaded the correct headers (1.40), it stopped segfaulting.
I noticed it when I had compiled with the debugging symbols -g and run a dbg backtrace..
Hope that helps...