Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikibooksThe Free Textbook Project
Search

Python Programming/Extending with C++

From Wikibooks, open books for an open world
<Python Programming
Previous: Extending with CIndexNext: Extending with Pyrex


There are different ways to extend Python with C and C++ code:

  • In plain C, using Python.h
  • Using Swig
  • Using Boost.Python, optionally with Py++ preprocessing
  • Using pybind11
  • UsingCython.

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

A Hello World Example

[edit |edit source]

The C++ source code (hellomodule.cpp)

[edit |edit source]
#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);}

setup.py

[edit |edit source]
#!/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`.

Using the extension module

[edit |edit source]

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!

An example with CGAL

[edit |edit source]

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>>>

Handling Python objects and errors

[edit |edit source]

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


External links

[edit |edit source]
Previous: Extending with CIndexNext: Extending with Pyrex
Retrieved from "https://en.wikibooks.org/w/index.php?title=Python_Programming/Extending_with_C%2B%2B&oldid=3676427"
Category:

[8]ページ先頭

©2009-2025 Movatter.jp