Boost.Python - <boost/python/class.hpp>, <boost/python/class_fwd.hpp>

###  | # 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 template `bases`
    Class template `bases` 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 `init`, `optional` 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 that is actually embedded in a Python object wrapping a `T` instance when `T`'s constructor is called or when a `T` or `T*` is converted to Python without the use of `ptr`, `ref`, or Call Policies such as `return_internal_reference`. 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 the `HeldType` instance, as shown in this example. This argument is not included in the init-expression passed to `def(init_expr)`, below, nor is it passed explicitly by users when Python instances of `T` are created. This idiom allows C++ virtual functions which will be overridden in Python to access the Python object so the Python method can be invoked. 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 of `HeldType`'s 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<T>.

#### Class template `class_` synopsis

    namespace boost { namespace python
    {
      template <class T
          , class Bases = bases<>
                , class HeldType = T
                , class NonCopyable = unspecified
               >
      class class_ : public object
      {
        // Constructors with default __init__
        class_(char const* name);
        class_(char const* name, char const* docstring);

        // Constructors, specifying non-default __init__
        template <class Init>
        class_(char const* name, Init);
        template <class Init>
        class_(char const* name, char const* docstring, Init);

        // Exposing additional __init__ functions
        template <class Init>
        class_& def(Init);

        // defining methods
        template <class F>
        class_& def(char const* name, F f);
        template <class Fn, class A1>
        class_& def(char const* name, Fn fn, A1 const&);
        template <class Fn, class A1, class A2>
        class_& def(char const* name, Fn fn, A1 const&, A2 const&);
        template <class Fn, class A1, class A2, class A3>
        class_& def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);

        // declaring method as static
        class_& staticmethod(char const* name);

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

        // Raw attribute modification
        template <class U>
        class_& setattr(char const* name, U const&);

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

        // exposing static data members
        template <class D>
        class_& def_readonly(char const* name, D const& d);
        template <class D>
        class_& def_readwrite(char const* name, D& d);

        // property creation
        template <class Get>
        void add_property(char const* name, Get const& fget, char const* doc=0);
        template <class Get, class Set>
        void add_property(
            char const* name, Get const& fget, Set const& fset, char const* doc=0);

        template <class Get>
        void add_static_property(char const* name, Get const& fget);
        template <class Get, class Set>
        void add_static_property(char const* name, Get const& fget, Set const& fset);

        // pickle support
        template <typename PickleSuite>
        self& def_pickle(PickleSuite const&);
        self& enable_pickling();
      };
    }}

#### Class template `class_` constructors

    class_(char const* name);
    class_(char const* name, char const* docstring);
    template <class Init>
    class_(char const* name, Init init_spec);
    template <class Init>
    class_(char const* name, char const* docstring, Init init_spec);

Requires: `name` is an ntbs which conforms to Python's identifier naming rules. If `docstring` is supplied, it must be an ntbs. If `init_spec` is supplied, it must be either the special enumeration constant `no_init` or an init-expression compatible with `T`.
Effects: Constructs a `class_` object holding a Boost.Python extension class named `name`. The `name`d attribute of the current scope is bound to the new extension class.
  - If supplied, the value of `docstring` is bound to the `__doc__` attribute of the extension class.
  - If `init_spec` is `no_init`, a special `__init__` function is generated which always raises a Python exception. Otherwise, `this->def(init_spec)` is called.
  - If `init_spec` is not supplied, `this->def(init<>())` is called.
Rationale:Allowing the user to specify constructor arguments in the `class_<>` constructor helps her to avoid the common run-time errors which result from invoking wrapped member functions without having exposed an `__init__` function which creates the requisite `T` instance. Types which are not default-constructible will cause a compile-time error unless `Init` is supplied. The user must always supply `name` as there is currently no portable method to derive the text of the class name from its type.

#### Class template `class_` modifier functions

    template <class Init>
    class_& def(Init init_expr);

Requires: `init_expr` is the result of an init-expression compatible with `T`.
Effects: For each valid prefix P of `Init`, adds an `__init__(`...`)` function overload to the extension class accepting P as arguments. Each overload generated constructs an object of `HeldType` according to the semantics described above, using a copy of `init_expr`'s call policies. If the longest valid prefix of `Init` contains N types and `init_expr` holds M keywords, an initial sequence of the keywords are used for all but the first N - M arguments of each overload.
Returns: `*this`
Rationale: Allows users to easily expose a class' constructor to Python.

    template <class F>
    class_& def(char const* name, Fn fn);
    template <class Fn, class A1>
    class_& def(char const* name, Fn fn, A1 const& a1);
    template <class Fn, class A1, class A2>
    class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2);
    template <class Fn, class A1, class A2, class A3>
    class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3);

Requires: `name` is an ntbs which conforms to Python's identifier naming rules.
  - If `a1` is the result of an overload-dispatch-expression, only the second form is allowed and fn must be a pointer to function or pointer to member function whose arity is the same as A1's maximum arity.
    Effects: For each prefix P of `Fn`'s sequence of argument types, beginning with the one whose length is `A1`'s minimum arity, adds a `name(`...`)` method overload to the extension class. Each overload generated invokes `a1`'s call-expression with P, using a copy of `a1`'s call policies. If the longest valid prefix of `A1` contains N types and `a1` holds M keywords, an initial sequence of the keywords are used for all but the first N - M arguments of each overload.
  - Otherwise, a single method overload is built around fn, which must not be null:
    - If fn is a function pointer, its first argument must be of the form `U`, `U cv&`, `U cv*`, or `U cv* const&`, where `T*` is convertible to `U*`, and `a1`-`a3`, if supplied, may be selected in any order from the table below.
    - Otherwise, if fn is a member function pointer, its target must be `T` or one of its public base classes, and `a1`-`a3`, if supplied, may be selected in any order from the table below.
    - Otherwise, `Fn` must be [derived from] `object`, and `a1-a2`, if supplied, may be selcted in any order from the first two rows of the table below. To be useful, `fn` should be callable.

    Memnonic Name | Requirements/Type properties | Effects
    --- | --- | ---
    docstring | Any ntbs. | Value will be bound to the `__doc__` attribute of the resulting method overload. If an earlier overload supplied a docstring, two newline characters and the new docstring are appended to it.
    policies | A model of CallPolicies | A copy will be used as the call policies of the resulting method overload.
    keywords | The result of a keyword-expression specifying no more arguments than the arity of `fn`. | A copy will be used as the call policies of the resulting method overload.

Returns: `*this`

    class_& staticmethod(char const* name);

Requires: `name` is an ntbs which conforms to Python's identifier naming rules, and corresponds to a method whose overloads have all been defined.
Effects: Replaces the existing named attribute x with the result of invoking `staticmethod(`x`)` in Python. Specifies that the corresponding method is static and therefore no object instance will be passed to it. This is equivalent to the Python statement:

      setattr(self, name, staticmethod(getattr(self, name)))

Note: Attempting to invoke `def(name,...)` after invoking `staticmethod(name)` will raise a RuntimeError.
Returns: `*this`

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

Effects: Adds a Python special method as described here.
Returns: `*this`

    template <class U>
    class_& setattr(char const* name, U const& u);

Requires: `name` is an ntbs which conforms to Python's identifier naming rules.
Effects: Converts u to Python and adds it to the attribute dictionary of the extension class:

  > `PyObject_SetAttrString(this->ptr(), name, object(u).ptr());`

Returns: `*this`

    template <class Get>
    void add_property(char const* name, Get const& fget, char const* doc=0);
    template <class Get, class Set>
    void add_property(
            char const* name, Get const& fget, Set const& fset, char const* doc=0);

Requires: `name` is an ntbs which conform to Python's identifier naming rules.
Effects: Creates a new Python `property` class instance, passing `object(fget)` (and `object(fset)` in the second form) with an (optional) docstring `doc` 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 functions that can be invoked from Python with attribute access syntax.

    template <class Get>
    void add_static_property(char const* name, Get const& fget);
    template <class Get, class Set>
    void add_static_property(char const* name, Get const& fget, Set const& fset);

Requires: `name` is an ntbs which conforms to Python's identifier naming rules.
Effects: Creates a Boost.Python.StaticProperty object, passing `object(fget)` (and `object(fset)` in the second form) to its constructor, then adds that property to the Python class under construction with the given attribute `name`. StaticProperty is a special subclass of Python's `property` class which can be called without an initial `self` argument.
Returns: `*this`
Rationale: Allows users to easily expose functions that can be invoked from Python with static attribute access syntax.

    template <class D>
    class_& def_readonly(char const* name, D T::*pm, char const* doc=0);
    template <class D>
    class_& def_readonly(char const* name, D const& d);

Requires: `name` is an ntbs which conforms to Python's identifier naming rules. `doc` is also an ntbs.
Effects:

      this->add_property(name, make_getter(pm), doc);

  and

      this->add_static_property(name, make_getter(d));

  respectively.
Returns: `*this`
Rationale: Allows users to easily expose a class' data member or free variable such that it can be inspected from Python with a natural syntax.

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

Effects:

      this->add_property(name, make_getter(pm), make_setter(pm), doc);

  and

      this->add_static_property(name, make_getter(d), make_setter(d));

  respectively.
Returns: `*this`
Rationale: Allows users to easily expose a class' data or free variable member such that it can be inspected and set from Python with a natural syntax.

    template <typename PickleSuite>
    class_& def_pickle(PickleSuite const&);

Requires: PickleSuite must be publically derived from `pickle_suite`.
Effects: Defines a legal combination of the special attributes and methods: `__getinitargs__`, `__getstate__`, `__setstate__`, `__getstate_manages_dict__`, `__safe_for_unpickling__`, `__reduce__`
Returns: `*this`
Rationale: Provides an easy to use high-level interface for establishing complete pickle support for the wrapped class. The user is protected by compile-time consistency checks.

    class_& enable_pickling();

Effects: Defines the `__reduce__` method and the `__safe_for_unpickling__` attribute.
Returns: `*this`
Rationale: Light-weight alternative to `def_pickle()`. Enables implementation of pickle support from Python.

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

An MPL sequence which can be used in `class_<`...`>` instantiations indicate a list of base classes.

#### 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 x, char const* y);
       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;

    class_<Foo,bases<Bar,Baz> >("Foo",
              "This is Foo's docstring."
              "It describes our Foo extension class",

              init<int,char const*>(args("x","y"), "__init__ docstring")
              )
       .def(init<double>())
       .def("get_name", &Foo::get_name, return_internal_reference<>())
       .def("set_name", &Foo::set_name)
       .def_readwrite("value", &Foo::value)
       ;

[1] By "previously-exposed" we mean that the for each `B` in `bases`, an instance of `class_<B, ...>` must have already been constructed.

    class_<Base>("Base");
    class_<Derived, bases<Base> >("Derived");

Revised 1 November, 2005

© Copyright Dave Abrahams 2002.