Thursday, September 18, 2008

Boost Python

Boost Python allows seamless interoperability between C++ and Python. In this article we'll setup Boost and build a simple hello world program that will be able to run in Python.

Boost, in case your unfamiliar, is a powerful set of libraries for C++. There website is at www.boost.org.

For this post we will be using Boost 1.36.0

Boost can be tricky to setup. Their documentation recommends using their own build tool called bjam, but I typically like to build it myself. For this article we'll walk through setting up Boost Python for Visual Studio 2005.

If you haven't already, download boost 1.36.0 library to your local machine. I've expanded the library to c:\download\boost\boost-1.36.0 on my machine.

Now open up Visual Studio 2005. New Project, Visual C++ -> Win32 -> Win32 Console Applicaion.

At the bottom of the screen enter the name for your project: PyHelloWorld, and the location, in my case c:\download\PyHelloWord. The solution name should be filled out for you (PyHelloWorld), and the check mark for 'Create directory for solution' should be checked.

Click Ok.

In the wizard click next. Select 'Dll' as application type, and Empty Project from additional options.

Click finish.

The project we just created will hold our client code, and our python bindings code. Before we can do that though we need to build Boost Python. To do this we'll create another project.

Right click on your solution 'PyHelloWorld', Click Add->Add New Project.

Like before we'll create a Win32 Console Application but we'll call it BoostPython this time. I've decided to keep the project located in the same solution folder of PyHelloWorld.

Follow the steps in the wizard again to create an empty, dll project.

In order to build boost python we need to include all the source files. Visual studio should have created a 'Source Files' filter in the BoostPython project. Right click and select Add->Existing Item...

You want to add all the files from

  • %PATH_TO_BOOST%\libs\python\src

  • %PATH_TO_BOOST%\libs\python\src\converter

  • %PATH_TO_BOOST%\libs\python\src\object



You now need to instruct the compiler that these are part of the boost source code. You do this by setting a preprocessor define. Right click on the BoostPython project, select c/c++ from the property pages, select Preprocessor, and append 'BOOST_PYTHON_SOURCE' to the end of the Preprocessor definitions. Its a semi-colon separated list so add a semi-colon then 'BOOST_PYTHON_SOURCE'.

Next set the include directory to find the Boost install. Right click on the BoostPython project, open the c/c++ -> General tab. Add your path to %PATH_TO_BOOST%, in my case that is C:\download\boost\boost_1_36_0

We've now set up the boost portion, we need to setup python by telling our project how to find our local python installation. First you'll need to download Python

The standard install saved Python under c:\Python25 on my machine. The standard python install comes with c++ headers so we'll point our BoostPython project at those headers.

Once again open the property page for BoostPython, C/C++ -> General , and add c:\Python25\include (or your python install) to the include path.

You can now build the BoostPython project, all the files should compile. The link step will fail though because it needs to link to the Python library as well. So one more tweak to the BoostPython project, this time Linker -> Input , Additional Dependencies. Add C:\Python25\libs\Python25.lib.

Build the project again and it should link successfully.

Okay now we have BoostPython ready to go. Lets Use it.

For the PyHelloWorld project we'll need to do the same steps as above to set the Include Path, and the Linker. More explicity you need to set:
  • include path to boost
  • include path to python
  • linker to python lib
If you don't remember how look above to see what we set.


Now create a new cpp file by right clicking on the project, add->New Item. Selecting cpp file. Call the file hello.cpp

Add the following to the file.
#define BOOST_ALL_NO_LIB
#include <boost/python.hpp>

char const* speak()
{
return "Hello World!";
}


BOOST_PYTHON_MODULE(PyHelloWorld)
{
using namespace boost::python;
def("speak", speak);
}



The first define instruct boost that we have already build it. The first function is your standard c++ function, the second is our python bindings.

Before you build you need to tell visual studio that this project is dependent on the BoostPython Project. Right click on PyHelloWorld project and click Project Dependencies. Select BoostPython.

Now Build. Everything should compile and build succesfully.

So what have we accomplished? We've build a dll that exposes method that python can understand. Lets test it and see if it works.

Open a Command shell, and navigate to your output directory. In my case its c:\download\PyHelloWorld\PyHelloWorld\debug. In order to make it easier for Python to find our dll lets rename it to pyd.

move PyHelloWorld.dll PyHelloWorld.pyd


Now lets load up the interpreter and try it out:


c:\download\PyHelloWorld\PyHelloWorld\debug>c:\Python25\python.exe
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import PyHelloWorld
>>> print PyHelloWorld.speak();
Hello World!
>>>



There you go, python interacting with your c++ file. Now that you have the BoostPython project created it would be easy to do this binding for more complex types. The official docs cover how to use this for classes, virtual functions, etc. For more info I recommend you start there. http://www.boost.org/doc/libs/1_36_0/libs/python/doc/tutorial/doc/html/index.html

Hope that helps...

1 comment:

tekpiks said...

I tried to do as you told:
The error I got was
>>> import hello
Traceback (most recent call last):
File "", line 1, in
ImportError: DLL load failed: The specified module could not be found.

Can you please help me figure out this?