Thursday, December 13, 2012

Using C++ Libraries from Python

It's been a while since my last post but here I am back with a very interesting post about Wrapping C++ libraries to be used in python.

First of all we are going to create a classical client-library program. You can find all the details in my previous post: http://linuxtortures.blogspot.fr/2012/02/shared-libraries-with-eclipse.html



Our library will contain a very simple method "getSomething()" that will return the string "something"



Configure the client project:

Right-click --> Properties

Under  C/C++ build, under Settings, under Cross G++ Compiler, under Includes, include the path "${workspace_loc:/Library/src}"

Under  C/C++ build, under Settings, under Cross G++ Linker,  under Libraries, include the library "Library" and the library search path "${workspace_loc:/Library/Debug}"

Configure the library project (Only if running under 64bits):

Right-click --> Properties

Under  C/C++ build, under Settings, under Cross G++ Compiler, under Miscellaneous, select the option "Position Independent Code (-fPIC)"

Compile the code and check that everything is ok, these should be the commands used:


Building file: ../src/Client.cpp
Invoking: Cross G++ Compiler
g++ -I"/home/javier/workspaceSharedLibraries/Library/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Client.d" -MT"src/Client.d" -o "src/Client.o" "../src/Client.cpp"
Finished building: ../src/Client.cpp

Building target: Client
Invoking: Cross G++ Linker
g++ -L"/home/javier/workspaceSharedLibraries/Library/Debug" -o "Client"  ./src/Client.o   -lLibrary
Finished building target: Client



Include the path where is located the compiled Library:



That should be enough to allow running our client:




Now we are going to create our Library wrapper, that will basically allows us to use the Library from python:

First of all, install all the needed dependencies:

sudo apt-get install python-devq                       
sudo apt-get install libboost-python-dev           

Create a new shared library and call it "PythonWrapper":



Important points:

1. Name of the module must match with the name of our library:

BOOST_PYTHON_MODULE(libPythonWrapper)

If you do not follow this advice, you will have issues when importing the library from python:


>>> import libPythonWrapper                                                                                      
Traceback (most recent call last):                                                                              
  File "<stdin>", line 1, in <module>                                                                         
ImportError: dynamic module does not define init function (initlibPythonWrapper)




2. Name of the python Class:

class_<Class>("Class")

The name under quotes is how it will looks on python our class, name it the same than in C++ in order to avoid confussion.

3. Name of the python method name:

.def("getSomething", &Class::getSomething)

Same advice, do not invent, and name it the same than our C++ method.

Add the following paths:



And link against the following libraries:


Compile the library, the output should be something like that:


Building file: ../src/PythonWrapper.cpp
Invoking: GCC C++ Compiler
g++ -I"/home/javier/workspaceSharedLibraries/Library/src" -I/usr/include/python2.7 -O0 -g3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"src/PythonWrapper.d" -MT"src/PythonWrapper.d" -o "src/PythonWrapper.o" "../src/PythonWrapper.cpp"
Finished building: ../src/PythonWrapper.cpp

Building target: libPythonWrapper.so
Invoking: GCC C++ Linker
g++ -L"/home/javier/workspaceSharedLibraries/Library/Debug" -shared -o "libPythonWrapper.so"  ./src/PythonWrapper.o   -lLibrary -lboost_python -lpython2.7
Finished building target: libPythonWrapper.so

Export the path of our original shared library and import the wrapper from python: