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

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.

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.

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

Calling a shared library from c++

i have a shared library with some functions stored inside it. i want to Access those functions by calling that library from another program. I have done this earlier in C.
Now i want to do the same using C++. I am pretty new to C++ and any suggestions are very much required. BTW, the shared library is written in C. Is it still possible for me to call this in a C++ program and use all the functions of it.
Please help me. An example program would be very very helpful.
i am using ubuntu 14.04 and the compiler is the native g++ that comes along with it.
Load shared libarary using dlopen, and load given symbol using dlsym. Link with -ldl.
So given a shared library hello.cpp, compile g++ -shared -fPIC -o libhello.so hello.cpp
#include <cstdio>
extern "C" void hello( const char* text ) {
printf("Hello, %s\n", text);
}
(shared libraries should be named lib*.so[.*])
Now calling in main.cpp, compile: g++ -o main main.cpp -ldl
#include <dlfcn.h>
extern "C" typedef void (*hello_t)( const char* text );
int main() {
void* lib = dlopen("./libhello.so", RTLD_LAZY);
hello_t hello = (hello_t)dlsym( lib, "hello" );
hello("World!");
dlclose(lib);
}
See C++ dlopen mini HOWTO.
You said you already did so in C. Actually C++ is based on C, so you still can do it in the same way you did before.
Usually the following steps are required:
Use some method provided by the library in your c++ code
Figure out which header provides that method, and include it in your .cpp file
Compile your C++ code against the headers of the library (compiler flags in the Makefile)
Link against the library ( Linker Flags in the Makefile )

Trying to use functions in a header/cpp file

I have two files:
hello.h and hello.cpp
hello.h
#ifndef __HELLO_H__
#define __HELLO_H__
using namespace std;
void PrintMessage();
#endif
hello.cpp
#include <iostream>
#include "hello.h"
using namespace std;
void PrintMessage()
{
cout << "I want to be displayed!";
}
Now, I want to use PrintMessage() in a new .cpp file, but I keep getting an error message. This is what I'm doing:
printingmessage.cpp
#include <iostream>
#include "hello.h"
using namespace std;
int main()
{
PrintMessage();
return 0;
}
Am I just doing something blatantly wrong? I do have all of them in the same folder; I assume it has something to do with Dev-C++ (what I'm using to write/compile/run), but I can't figure it out. Anyone have any ideas?
I created a folder on my desktop, put all three files inside, and I tried to compile my printingmessage.cpp file exactly as it is. This is the error I'm getting:
[Linker error] Undefined reference to 'PrintMessage()'
i don't know dev C++ , but i would strongly advise if you do any serious coding to learn/move to the terminal and use make files, or a newer IDE such as visual studios.
heres a short script you can run save it as bash.sh
something like this
g++ hello.cpp -O2 -g -c
g++ hello.o printmessage.cpp -Wall -O2 -o print
then run it with ./print
I assume it has something to do with Dev-C++ (what I'm using to
write/compile/run), but I can't figure it out.
I guess so, too. Behind the scenes, the following things have to happen:
Both files get compiled. This creates a *.obj file for every *.cpp file, and uses the header.
The object files are linked against one another and possibly against required libraries.
Your problem lies in the “one another” part of the second step: the code compiles all right, but linking fails. The header file is irrelevant at that point. More precisely, the linker invocation for printingmessage.obj contains a reference to a function which isn't defined in that object file or any of the default libraries. Most likely the problem is due to the *.cpp files not being part of the same project. You need to create a multi-source-file project where you can link multiple object files. How you do that with Dev-C++ is probably somewhere in their manuals.

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.