...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
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*);
true
nothing
PyObject* postcall(PyObject*, PyObject* result);
result
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
T is not a reference type. If T is a pointer type, T is const char* or PyObject*.
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 |
the position of the argument to be returned. |
1 |
Base |
A model of |
Used for policy composition. Any |
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);
PyTuple_Check(args)
!= 0
and PyTuple_Size(args) != 0
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 |
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 ( |
|
Base |
A model of |
Used for policy composition. Any |
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);
PyTuple_Check(args)
!= 0
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 |
|
Base |
A model of |
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 |
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 ( |
|
ward |
A positive compile-time constant of type |
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 ( |
|
Base |
A model of |
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);
PyTuple_Check(args)
!= 0
Makes the lifetime of the argument indicated by ward dependent on the lifetime of the argument indicated by custodian.
false and PyErr_Occurred() != 0 upon failure, true otherwise.
Parameter |
Requirements |
Description |
Default |
---|---|---|---|
custodian |
A positive compile-time constant of type |
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 ( |
|
ward |
A positive compile-time constant of type |
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 ( |
|
Base |
A model of |
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);
PyTuple_Check(args)
!= 0
,
result !=
0
Makes the lifetime of the object indicated by ward dependent on the lifetime of the object indicated by custodian.
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; };