C++ Boost

Boost.Python

Headers <boost/python/class.hpp>, <boost/python/class_fwd.hpp>


Contents

Introduction
Classes
Class template class_
Class class_ synopsis
Class class_ constructors
Class class_ modifier functions
Class class_ observer functions
Class template bases
Class bases synopsis
Class template args
Class args synopsis
Example(s)

Introduction

<boost/python/class.hpp> defines the interface through which users expose their C++ classes to Python. It declares the class_ class template, which is parameterized on the class type being exposed. It also exposes the args and bases utility class templates, which are used in conjunction with class_.

<boost/python/class_fwd.hpp> contains a forward declaration of the class_ class template.

Classes

Class template class_<T, Bases, HeldType, NonCopyable>

Creates a Python class associated with the C++ type passed as its first parameter. Although it has four template parameters, only the first one is required. The three optional arguments can actually be supplied in any order; Boost.Python determines the role of the argument from its type.

Template Parameter Requirements Semantics Default
T A class type. The class being wrapped
Bases A specialization of bases<...> which specifies previously-exposed C++ base classes of T[1]. Registers from_python conversions from wrapped T instances to each of its exposed direct and indirect bases. For each polymorphic base B, registers conversions from indirectly-held wrapped B instances to T. bases<>
HeldType Must be T, a class derived from T, or a Dereferenceable type for which pointee<HeldType>::type is T or a class derived from T. Specifies the type which is actually embedded in a Python object wrapping a T instance. More details below. T
NonCopyable If supplied, must be boost::noncopyable. Suppresses automatic registration of to_python conversions which copy T instances. Required when T has no publicly-accessible copy constructor. An unspecified type other than boost::noncopyable.

HeldType Semantics

  1. If HeldType is derived from T, its exposed constructor(s) must accept an initial PyObject* argument which refers back to the Python object that contains it, as shown in this example. This argument is not included in the argument list type passed to def_init(), below, nor is it passed explicitly by users when Python instances of T are created. This is the idiom which allows C++ virtual functions to be overridden in Python. Boost.Python automatically registers additional converters which allow wrapped instances of T to be passed to wrapped C++ functions expecting HeldType arguments.
  2. Because Boost.Python will always allow wrapped instances of T to be passed in place of HeldType arguments, specifying a smart pointer for HeldType allows users to pass Python T instances where a smart pointer-to-T is expected. Smart pointers such as std::auto_ptr<> or boost::shared_ptr<> which contain a nested type element_type designating the referent type are automatically supported; additional smart pointer types can be supported by specializing pointee<HeldType>.
  3. As in case 1 above, when HeldType is a smart pointer to a class derived from T, the initial PyObject* argument must be supplied by all exposed constructors.
  4. Except in cases 1 and 3, users may optionally specify that T itself gets initialized with a similar initial PyObject* argument by specializing has_back_reference.

Class template class_ synopsis

namespace boost { namespace python
{
  template <class T
            , class Bases = bases<>
            , class HeldType = T
            , class NonCopyable = unspecified
           >
  class class_
  {
    class_();
    class_(char const* name);

    // exposing constructors
    class_& def_init();

    template <class Args>
    class_& def_init(Args const& = Args());

    template <class Args, class CallPolicy>
    class_& def_init(Args const&, CallPolicy policy);

    // exposing member functions
    template <class F>
    class_& def(char const* name, F f);

    template <class Fn, class CallPolies>
    class_& def(char const* name, Fn fn, CallPolies);

    // exposing operators
    template <unspecified>
    class_& def(detail::operator_<unspecified>);

    // exposing data members
    template <class D>
    class_& def_readonly(char const* name, D T::*pm);

    template <class D>
    class_& def_readwrite(char const* name, D T::*pm);

    // Raw attribute modification
    class_& setattr(char const* name, ref const&);

    // property creation
    void add_property(char const* name, ref const& fget);
    void add_property(char const* name, ref const& fget, ref const& fset);

    // accessing the Python class object
    ref object() const;
  };
}}

Class template class_ constructors

class_();
Requires: The platform's std::type_info::name() implementation produces a string which corresponds to the type's declaration in C++
Effects: Constructs a class_ object which generates a Boost.Python extension class with the same name as T.
Rationale: Many platforms can generate reasonable names for Python classes without user intervention.
class_(char const* name);
Requires: name is a ntbs which conforms to Python's identifier naming rules.
Effects: Constructs a class_ object which generates a Boost.Python extension class named name.
Rationale: Gives the user full control over class naming.

Class template class_ modifier functions

class_& def_init();

template <class Args>
class_& def_init(Args const& argument_types);

template <class Args, class CallPolicies>
class_& def_init(Args const& argument_types, CallPolicies policies);
Requires: Args is an MPL sequence of C++ argument types (A1, A2,... AN) such that if a1, a2... aN are objects of type A1, A2,... AN respectively, the expression T(a1, a2... aN) is valid. In the first form, the expression T() must be valid.
Effects: Adds the result of make_constructor<args<>,Holder>(), make_constructor<Args,Holder>(), or make_constructor<Args,Holder>(policies), respectively, to the Boost.Python extension class being defined under the name "__init__". Holder is a concrete subclass of instance_holder which holds the HeldType. If the extension class already has an "__init__" attribute, the usual overloading procedure applies.
Returns: *this
Rationale: Allows users to easily expose a class' constructor to Python.

template <class F>
class_& def(char const* name, F f);

template <class Fn, class CallPolicies>
class_& def(char const* name, Fn f, CallPolicies policies);
Requires: f is a non-null pointer-to-function or pointer-to-member-function, or a callable Python object passed as a PyObject* or ref. name is a ntbs which conforms to Python's identifier naming rules. In the first form, the return type of f is not a reference and is not a pointer other than char const* or PyObject*. In the second form policies is a model of CallPolicies.
Effects: Adds the result of make_function(f) or make_function(f, policies) to the Boost.Python extension class being defined, with the given name. If the extension class already has an attribute named name, the usual overloading procedure applies.
Returns: *this
template <unspecified>
class_& def(detail::operator_<unspecified>);
Effects: Adds a Python special method as described here.
Returns: *this
template <class F>
class_& setattr(char const* name, ref x);
Requires: name is a ntbs which conforms to Python's identifier naming rules.
Effects: PyObject_SetAttrString(this->object(), name, x.get());
Returns: *this

void add_property(char const* name, ref const& fget);
void add_property(char const* name, ref const& fget, ref const& fset);
Requires: name is a ntbs which conforms to Python's identifier naming rules.
Effects: Creates a new Python property class instance, passing fget.get() (and fset.get() in the second form) to its constructor, then adds that property to the Python class object under construction with the given attribute name.
Returns: *this
Rationale: Allows users to easily expose a class' data member such that it can be inspected from Python with a natural syntax.

    template <class D>
    class_& def_readonly(char const* name, D T::*pm);
Requires: name is a ntbs which conforms to Python's identifier naming rules.
Effects:
this->add_property(name, ref(make_getter(pm)));
Returns: *this
Rationale: Allows users to easily expose a class' data member such that it can be inspected from Python with a natural syntax.

template <class D>
class_& def_readwrite(char const* name, D T::*pm);
Effects:
ref fget(make_getter(pm));
ref fset(make_setter(pm));
this->add_property(name, fget, fset);
Returns: *this
Rationale: Allows users to easily expose a class' data member such that it can be inspected and set from Python with a natural syntax.

Class template class_ observer functions

ref object() const;
Returns: A ref object which holds a reference to the Boost.Python extension class object created by the class_ constructor.
Rationale: Mostly not needed by users, since module::add() uses this to insert the extension class in the module.

Class template args<T1, T2,...TN>

A conveniently-named MPL sequence which users pass to def_init calls to make their code more readable.

Class template args synopsis

namespace boost { namespace python
{
  template <T1 = unspecified,...TN = unspecified>
  struct args
  {};
}}

Class template bases<T1, T2,...TN>

An MPL sequence which can be used in class_<...> instantiations indicate a list of base classes. Although users can pass any MPL sequence in place of args, above, the use of bases to indicate base classes is mandatory.

Class template bases synopsis

namespace boost { namespace python
{
  template <T1 = unspecified,...TN = unspecified>
  struct bases
  {};
}}

Example(s)

Given a C++ class declaration:

class Foo : public Bar, public Baz
{
 public:
   Foo(int, char const*);
   Foo(double);

   std::string const& name() { return m_name; }
   void name(char const*);

   double value; // public data
 private:
   ...
};
A corresponding Boost.Python extension class can be created with:
using namespace boost::python;

ref foo = class_<Foo,bases<Bar,Baz> >()
   .def_init(args<int,char const*>())
   .def_init(args<double>())
   .def("get_name", &Foo::get_name, return_internal_reference<>())
   .def("set_name", &Foo::set_name)
   .def_readwrite("value", &Foo::value)
   .object();

[1] By "previously-exposed" we mean that the for each B in bases, an instance of class_<B> must have already been constructed. Ensuring this in a portable manner when a class and its bases are exposed in the same module entails using separate full-expressions, rather than chaining consecutive definitions with ".add(...).
module m("module_name");
m.add(class_<Base>()
        .def_init());
m.add(class_<Derived, bases<Base>>()
        .def_init());
Revised 09 May, 2002

© Copyright Dave Abrahams 2002. All Rights Reserved.