There are different ways to extend Python with C and C++ code:
This page describes Boost.Python. Before the emergence of Cython, it was the most comfortable way of writingC++ extension modules.
Boost.Python comes bundled with the Boost C++ Libraries. To install it on an Ubuntu system, you might need to run the following commands
$ sudo apt-get install libboost-python-dev $ sudo apt-get install python-dev
#include<iostream>usingnamespacestd;voidsay_hello(constchar*name){cout<<"Hello "<<name<<"!\n";}#include<boost/python/module.hpp>#include<boost/python/def.hpp>usingnamespaceboost::python;BOOST_PYTHON_MODULE(hello){def("say_hello",say_hello);}
#!/usr/bin/env pythonfromdistutils.coreimportsetupfromdistutils.extensionimportExtensionsetup(name="PackageName",ext_modules=[Extension("hello",["hellomodule.cpp"],libraries=["boost_python"])])
Now we can build our module with
python setup.py build
The module `hello.so` will end up in e.g `build/lib.linux-i686-2.4`.
Change to the subdirectory where the file `hello.so` resides. In an interactive python session you can use the module as follows.
>>> import hello>>> hello.say_hello("World")Hello World!
Some, but not all, functions of the CGAL library already have Python bindings. Here an example is provided for a case without such a binding and how it might be implemented. The example is taken from theCGAL Documentation.
// test.cppusingnamespacestd;/* PYTHON */#include<boost/python.hpp>#include<boost/python/module.hpp>#include<boost/python/def.hpp>namespacepython=boost::python;/* CGAL */#include<CGAL/Cartesian.h>#include<CGAL/Range_segment_tree_traits.h>#include<CGAL/Range_tree_k.h>typedefCGAL::Cartesian<double>K;typedefCGAL::Range_tree_map_traits_2<K,char>Traits;typedefCGAL::Range_tree_2<Traits>Range_tree_2_type;typedefTraits::KeyKey;typedefTraits::IntervalInterval;Range_tree_2_type*Range_tree_2=newRange_tree_2_type;voidcreate_tree(){typedefTraits::KeyKey;typedefTraits::IntervalInterval;std::vector<Key>InputList,OutputList;InputList.push_back(Key(K::Point_2(8,5.1),'a'));InputList.push_back(Key(K::Point_2(1.0,1.1),'b'));InputList.push_back(Key(K::Point_2(3,2.1),'c'));Range_tree_2->make_tree(InputList.begin(),InputList.end());Intervalwin(Interval(K::Point_2(1,2.1),K::Point_2(8.1,8.2)));std::cout<<"\n Window Query:\n";Range_tree_2->window_query(win,std::back_inserter(OutputList));std::vector<Key>::iteratorcurrent=OutputList.begin();while(current!=OutputList.end()){std::cout<<" "<<(*current).first.x()<<","<<(*current).first.y()<<":"<<(*current).second<<std::endl;current++;}std::cout<<"\n Done\n";}voidinitcreate_tree(){;}usingnamespaceboost::python;BOOST_PYTHON_MODULE(test){def("create_tree",create_tree,"");}
// setup.py#!/usr/bin/env pythonfromdistutils.coreimportsetupfromdistutils.extensionimportExtensionsetup(name="PackageName",ext_modules=[Extension("test",["test.cpp"],libraries=["boost_python"])])
We then compile and run the module as follows:
$ python setup.py build$ cd build/lib*$ python>>> import test>>> test.create_tree()Window Query: 3,2.1:c 8,5.1:aDone>>>
One can also handle more complex data, e.g. Python objects like lists. The attributes are accessed with the extract function executed on the objects "attr" function output. We can also throw errors by telling the library that an error has occurred and returning. In the following case, we have written a C++ function called "afunction" which we want to call. The function takes an integer N and a vector of length N as input, we have to convert the python list to a vector of strings before calling the function.
#include<vector>usingnamespacestd;void_afunction_wrapper(intN,boost::python::listmapping){intmapping_length=boost::python::extract<int>(mapping.attr("__len__")());//Do Error checking, the mapping needs to be at least as long as Nif(mapping_length<N){PyErr_SetString(PyExc_ValueError,"The string mapping must be at least of length N");boost::python::throw_error_already_set();return;}vector<string>mystrings(mapping_length);for(inti=0;i<mapping_length;i++){mystrings[i]=boost::python::extract<charconst*>(mapping[i]);}//now call our C++ function_afunction(N,mystrings);}usingnamespaceboost::python;BOOST_PYTHON_MODULE(c_afunction){def("afunction",_afunction_wrapper);}