Boost
C++ Libraries
...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
This version of Boost is under active development. You are currently in the develop branch. The current version is 1.91.0.
Boost.Python supports docstrings with automatic appending of Pythonic
and C++ signatures. This feature is implemented by class function_doc_signature_generator. The
class uses all of the overloads, supplied arg names and default values,
as well as the user-defined docstrings, to generate documentation for
a given function.
The class has only one public function which returns a list of strings documenting the overloads of a function.
namespace boost { namespace python { namespace objects { class function_doc_signature_generator { public: static list function_doc_signatures(function const *f); }; }}}
#include <boost/python/module.hpp> #include <boost/python/def.hpp> #include <boost/python/args.hpp> #include <boost/python/tuple.hpp> #include <boost/python/class.hpp> #include <boost/python/overloads.hpp> #include <boost/python/raw_function.hpp> using namespace boost::python; tuple f(int x = 1, double y = 4.25, char const* z = "wow") { return make_tuple(x, y, z); } BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3) struct X { tuple f(int x = 1, double y = 4.25, char const* z = "wow") { return make_tuple(x, y, z); } }; BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_f_overloads, X::f, 0, 3) tuple raw_func(tuple args, dict kw) { return make_tuple(args, kw); } BOOST_PYTHON_MODULE(args_ext) { def("f", f, (arg("x")=1, arg("y")=4.25, arg("z")="wow") , "This is f's docstring" ); def("raw", raw_function(raw_func)); def("f1", f, f_overloads("f1's docstring", args("x", "y", "z"))); class_<X>("X", "This is X's docstring", init<>(args("self"))) .def("f", &X::f , "This is X.f's docstring" , args("self","x", "y", "z")) ; }
Python code:
>>> import args_ext >>> help(args_ext) Help on module args_ext: NAME args_ext FILE args_ext.pyd CLASSES Boost.Python.instance(__builtin__.object) X class X(Boost.Python.instance) | This is X's docstring | | Method resolution order: | X | Boost.Python.instance | __builtin__.object | | Methods defined here: | | __init__(...) | __init__( (object)self) -> None : | C++ signature: | void __init__(struct _object *) | | f(...) | f( (X)self, (int)x, (float)y, (str)z) -> tuple : This is X.f's docstring | C++ signature: | class boost::python::tuple f(struct X {lvalue},int,double,char const *) | | ................. | FUNCTIONS f(...) f([ (int)x=1 [, (float)y=4.25 [, (str)z='wow']]]) -> tuple : This is f's docstring C++ signature: class boost::python::tuple f([ int=1 [,double=4.25 [,char const *='wow']]]) f1(...) f1([ (int)x [, (float)y [, (str)z]]]) -> tuple : f1's docstring C++ signature: class boost::python::tuple f1([ int [,double [,char const *]]]) raw(...) object raw(tuple args, dict kwds) : C++ signature: object raw(tuple args, dict kwds)
To support Pythonic signatures the converters should supply a get_pytype function returning a pointer
to the associated PyTypeObject.
See for example ResultConverter or to_python_converter. The classes
in this header file are meant to be used when implmenting get_pytype. There are also _direct versions of the templates of
class T
which should be used with undecorated type parameter, expected to be
in the conversion registry when the module loads.
This template generates a static get_pytype
member returning the template parameter.
namespace boost { namespace python { namespace converter{ template < PyTypeObject const *pytype > class wrap_pytype { public: static PyTypeObject const *get_pytype(){return pytype; } }; }}}
This template should be used with template parameters which are (possibly
decorated) types exported to python using class_. The generated a static
get_pytype member returns
the corresponding python type.
namespace boost { namespace python { namespace converter{ template < class T > class registered_pytype { public: static PyTypeObject const *get_pytype(); }; }}}
This template generates a static get_pytype
member which inspects the registered from_python
converters for the type T
and returns a matching python type.
namespace boost { namespace python { namespace converter{ template < class T > class expected_from_python_type { public: static PyTypeObject const *get_pytype(); }; }}}
This template generates a static get_pytype
member returning the python type to which T
can be converted.
namespace boost { namespace python { namespace converter{ template < class T > class to_python_target_type { public: static PyTypeObject const *get_pytype(); }; }}}
This example presumes that someone has implemented the standard noddy
example module from the Python documentation, and placed the corresponding
declarations in "noddy.h". Because noddy_NoddyObject
is the ultimate trivial extension type, the example is a bit contrived:
it wraps a function for which all information is contained in the type
of its return value.
C++ module definition:
#include <boost/python/reference.hpp> #include <boost/python/module.hpp> #include "noddy.h" struct tag {}; tag make_tag() { return tag(); } using namespace boost::python; struct tag_to_noddy #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported : wrap_pytype<&noddy_NoddyType> //inherits get_pytype from wrap_pytype #endif { static PyObject* convert(tag const& x) { return PyObject_New(noddy_NoddyObject, &noddy_NoddyType); } }; BOOST_PYTHON_MODULE(to_python_converter) { def("make_tag", make_tag); to_python_converter<tag, tag_to_noddy #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported , true #endif >(); //"true" because tag_to_noddy has member get_pytype }
The following example registers to and from python converters using the templates expected_from_python_type and to_pyhton_target_type.
#include <boost/python/module.hpp> #include <boost/python/def.hpp> #include <boost/python/extract.hpp> #include <boost/python/to_python_converter.hpp> #include <boost/python/class.hpp> using namespace boost::python; struct A { }; struct B { A a; B(const A& a_):a(a_){} }; // Converter from A to python int struct BToPython #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported : converter::to_python_target_type<A> //inherits get_pytype #endif { static PyObject* convert(const B& b) { return incref(object(b.a).ptr()); } }; // Conversion from python int to A struct BFromPython { BFromPython() { boost::python::converter::registry::push_back ( &convertible , &construct , type_id< B >() #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported , &converter::expected_from_python_type<A>::get_pytype//convertible to A can be converted to B #endif ); } static void* convertible(PyObject* obj_ptr) { extract<const A&> ex(obj_ptr); if (!ex.check()) return 0; return obj_ptr; } static void construct( PyObject* obj_ptr, converter::rvalue_from_python_stage1_data* data) { void* storage = ( (converter::rvalue_from_python_storage< B >*)data)-> storage.bytes; extract<const A&> ex(obj_ptr); new (storage) B(ex()); data->convertible = storage; } }; B func(const B& b) { return b ; } BOOST_PYTHON_MODULE(pytype_function_ext) { to_python_converter< B , BToPython #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported ,true #endif >(); //has get_pytype BFromPython(); class_<A>("A") ; def("func", &func); } >>> from pytype_function_ext import * >>> print func.__doc__ func( (A)arg1) -> A : C++ signature: struct B func(struct B)