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

PrevUpHomeNext

Models of CallPolicies

boost/python/default_call_policies.hpp
boost/python/return_arg.hpp
boost/python/return_internal_reference.hpp
boost/python/return_value_policy.hpp
boost/python/with_custodian_and_ward.hpp

default_call_policies is a model of CallPolicies with no precall or postcall behavior and a result_converter which handles by-value returns. Wrapped C++ functions and member functions use default_call_policies unless otherwise specified. You may find it convenient to derive new models of CallPolicies from default_call_policies.

namespace boost { namespace python
{
    struct default_call_policies
    {
        static bool precall(PyObject*);
        static PyObject* postcall(PyObject*, PyObject* result);
        typedef default_result_converter result_converter;
        template <class Sig> struct extract_return_type : mpl::front<Sig>{};
    };
}}
bool precall(PyObject*);

Returns

true

Throws

nothing

PyObject* postcall(PyObject*, PyObject* result);

Returns

result

Throws

nothing

default_result_converter is a model of ResultConverterGenerator which can be used to wrap C++ functions returning non-pointer types, char const*, and PyObject*, by-value.

namespace boost { namespace python
{
    struct default_result_converter
    {
        template <class T> struct apply;
    };
}}
template <class T> struct apply

Requires

T is not a reference type. If T is a pointer type, T is const char* or PyObject*.

Returns

typedef to_python_value<T const&> type;

This example comes from the Boost.Python implementation itself. Because the return_value_policy class template does not implement precall or postcall behavior, its default base class is default_call_policies:

template <class Handler, class Base = default_call_policies>
struct return_value_policy : Base
{
   typedef Handler result_converter;
};

return_arg and return_self instantiations are models of CallPolicies which return the specified argument parameter (usually *this) of a wrapped (member) function.

Parameter

Requirements

Description

Default

arg_pos

A positive compile-time constant of type std::size_t.

the position of the argument to be returned.

1

Base

A model of CallPolicies

Used for policy composition. Any result_converter it supplies will be overridden by return_arg, but its precall and postcall policies are composed as described here CallPolicies.

default_call_policies

namespace boost { namespace python
{
   template <size_t arg_pos=1, class Base = default_call_policies>
   struct return_arg : Base
   {
      static PyObject* postcall(PyObject*, PyObject* result);
      struct result_converter{ template <class T> struct apply; };
      template <class Sig> struct extract_return_type : mpl::at_c<Sig, arg_pos>{};

   };
}}
PyObject* postcall(PyObject* args, PyObject* result);

Requires

PyTuple_Check(args) != 0 and PyTuple_Size(args) != 0

Returns

PyTuple_GetItem(args,arg_pos-1)

namespace boost { namespace python
{
   template <class Base = default_call_policies>
   struct return_self
     : return_arg<1,Base>
   {};
}}

C++ module definition:

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/return_arg.hpp>

struct Widget
{
   Widget() :sensitive_(true){}
   bool get_sensitive() const { return sensitive_; }
   void set_sensitive(bool s) { this->sensitive_ = s; }
 private:
   bool sensitive_;
};

struct Label : Widget
{
   Label() {}

   std::string  get_label() const { return label_; }
   void set_label(const std::string &l){ label_ = l; }

 private:
   std::string label_;
};

using namespace boost::python;
BOOST_PYTHON_MODULE(return_self_ext)
{
   class_<widget>("Widget")
      .def("sensitive", &Widget::get_sensitive)
      .def("sensitive", &Widget::set_sensitive, return_self<>())
      ;

   class_<Label, bases<Widget> >("Label")
      .def("label", &Label::get_label)
      .def("label", &Label::set_label, return_self<>())
      ;
}

Python code:

>>> from return_self_ext import *
>>> l1 = Label().label("foo").sensitive(false)
>>> l2 = Label().sensitive(false).label("foo")

return_internal_reference instantiations are models of CallPolicies which allow pointers and references to objects held internally by a free or member function argument or from the target of a member function to be returned safely without making a copy of the referent. The default for its first template argument handles the common case where the containing object is the target (*this) of a wrapped member function.

Parameter

Requirements

Description

Default

owner_arg

A positive compile-time constant of type std::size_t.

The index of the parameter which contains the object to which the reference or pointer is being returned. If used to wrap a member function, parameter 1 is the target object (*this). Note that if the target Python object type doesn't support weak references, a Python TypeError exception will be raised when the function being wrapped is called.

Base

A model of CallPolicies

Used for policy composition. Any result_converter it supplies will be overridden by return_internal_reference, but its precall and postcall policies are composed as described here CallPolicies.

default_call_policies

namespace boost { namespace python
{
   template <std::size_t owner_arg = 1, class Base = default_call_policies>
   struct return_internal_reference : Base
   {
      static PyObject* postcall(PyObject*, PyObject* result);
      typedef reference_existing_object result_converter;
   };
}}
PyObject* postcall(PyObject* args, PyObject* result);

Requires

PyTuple_Check(args) != 0

Returns

with_custodian_and_ward_postcall::postcall(args, result)

C++ module definition:

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/return_internal_reference.hpp>

class Bar
{
 public:
   Bar(int x) : x(x) {}
   int get_x() const { return x; }
   void set_x(int x) { this->x = x; }
 private:
   int x;
};

class Foo
{
 public:
   Foo(int x) : b(x) {}

   // Returns an internal reference
   Bar const& get_bar() const { return b; }

 private:
   Bar b;
};

using namespace boost::python;
BOOST_PYTHON_MODULE(internal_refs)
{
   class_<Bar>("Bar", init<int>())
      .def("get_x", &Bar::get_x)
      .def("set_x", &Bar::set_x)
      ;

   class_<Foo>("Foo", init<int>())
      .def("get_bar", &Foo::get_bar
          , return_internal_reference<>())
      ;
}

Python code:

>>> from internal_refs import *
>>> f = Foo(3)
>>> b1 = f.get_bar()
>>> b2 = f.get_bar()
>>> b1.get_x()
3
>>> b2.get_x()
3
>>> b1.set_x(42)
>>> b2.get_x()
42

return_value_policy instantiations are simply models of CallPolicies which are composed of a ResultConverterGenerator and optional Base CallPolicies.

Parameter

Requirements

Default

ResultConverterGenerator

A model of ResultConverterGenerator

Base

A model of CallPolicies

default_call_policies

namespace boost { namespace python
{
  template <class ResultConverterGenerator, class Base = default_call_policies>
  struct return_value_policy : Base
  {
      typedef ResultConverterGenerator result_converter;
  };
}}

C++ module definition:

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/copy_const_reference.hpp>
#include <boost/python/return_value_policy.hpp>

// classes to wrap
struct Bar { int x; }

struct Foo {
   Foo(int x) : { b.x = x; }
   Bar const& get_bar() const { return b; }
 private:
   Bar b;
};

// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
   class_<Bar>("Bar");

   class_<Foo>("Foo", init<int>())
      .def("get_bar", &Foo::get_bar
          , return_value_policy<copy_const_reference>())
      ;
}

Python code:

>>> from my_module import *
>>> f = Foo(3)         # create a Foo object
>>> b = f.get_bar()    # make a copy of the internal Bar object

This header provides facilities for establishing a lifetime dependency between two of a function's Python argument or result objects. The ward object will not be destroyed until after the custodian as long as the custodian object supports weak references (Boost.Python extension classes all support weak references). If the custodian object does not support weak references and is not None, an appropriate exception will be thrown. The two class templates with_custodian_and_ward and with_custodian_and_ward_postcall differ in the point at which they take effect.

In order to reduce the chance of inadvertently creating dangling pointers, the default is to do lifetime binding before the underlying C++ object is invoked. However, before invocation the result object is not available, so with_custodian_and_ward_postcall is provided to bind lifetimes after invocation. Also, if a C++ exception is thrown after with_custodian_and_ward<>::precall but before the underlying C++ object actually stores a pointer, the lifetime of the custodian and ward objects will be artificially bound together, so one might choose with_custodian_and_ward_postcall instead, depending on the semantics of the function being wrapped.

Please note that this is not the appropriate tool to use when wrapping functions which transfer ownership of a raw pointer across the function-call boundary. Please see the FAQ if you want to do that.

Parameter

Requirements

Description

Default

custodian

A positive compile-time constant of type std::size_t.

The 1-based index of the parameter which is the dependency in the lifetime relationship to be established. If used to wrap a member function, parameter 1 is the target object (*this). Note that if the target Python object type doesn't support weak references, a Python TypeError exception will be raised when the C++ object being wrapped is called.

ward

A positive compile-time constant of type std::size_t.

The 1-based index of the parameter which is the dependent in the lifetime relationship to be established. If used to wrap a member function, parameter 1 is the target object (*this).

Base

A model of CallPolicies

Used for policy composition.

default_call_policies

namespace boost { namespace python
{
   template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
   struct with_custodian_and_ward : Base
   {
      static bool precall(PyObject* args);
   };
}}
bool precall(PyObject* args);

Requires

PyTuple_Check(args) != 0

Effects

Makes the lifetime of the argument indicated by ward dependent on the lifetime of the argument indicated by custodian.

Returns

false and PyErr_Occurred() != 0 upon failure, true otherwise.

Parameter

Requirements

Description

Default

custodian

A positive compile-time constant of type std::size_t.

The index of the parameter which is the dependency in the lifetime relationship to be established. Zero indicates the result object; 1 indicates the first argument. If used to wrap a member function, parameter 1 is the target object (*this). Note that if the target Python object type doesn't support weak references, a Python TypeError exception will be raised when the C++ object being wrapped is called.

ward

A positive compile-time constant of type std::size_t.

The index of the parameter which is the dependent in the lifetime relationship to be established. Zero indicates the result object; 1 indicates the first argument. If used to wrap a member function, parameter 1 is the target object (*this).

Base

A model of CallPolicies

Used for policy composition.

default_call_policies

namespace boost { namespace python
{
   template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
   struct with_custodian_and_ward_postcall : Base
   {
      static PyObject* postcall(PyObject* args, PyObject* result);
   };
}}
PyObject *postcall(PyObject* args, PyObject* result);

Requires

PyTuple_Check(args) != 0, result != 0

Effects

Makes the lifetime of the object indicated by ward dependent on the lifetime of the object indicated by custodian.

Returns

0 and PyErr_Occurred() != 0 upon failure, true otherwise.

The following example shows how with_custodian_and_ward_postcall is used by the library to implement return_internal_reference

template <std::size_t owner_arg = 1, class Base = default_call_policies>
struct return_internal_reference
    : with_custodian_and_ward_postcall<0, owner_arg, Base>
{
   typedef reference_existing_object result_converter;
};

PrevUpHomeNext