PrevUpHomeNext

Models of ResultConverterGenerator

boost/python/copy_const_reference.hpp
boost/python/copy_non_const_reference.hpp
boost/python/manage_new_object.hpp
boost/python/reference_existing_object.hpp
boost/python/return_by_value.hpp
boost/python/return_opaque_pointer.hpp

copy_const_reference is a model of ResultConverterGenerator which can be used to wrap C++ functions returning a reference-to-const type such that the referenced value is copied into a new Python object.

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

Requires

T is U const& for some U.

Returns

typedef to_python_value<T> type;

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

copy_non_const_reference is a model of ResultConverterGenerator which can be used to wrap C++ functions returning a reference-to-non-const type such that the referenced value is copied into a new Python object.

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

Requires

T is U & for some non-const U.

Returns

typedef to_python_value<T> type;

C++ module definition:

#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/copy_non_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& get_bar() { 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_non_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

manage_new_object is a model of ResultConverterGenerator which can be used to wrap C++ functions which return a pointer to an object allocated with a new-expression, and expect the caller to take responsibility for deleting that object.

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

Requires

T is U* for some U.

Returns

typedef to_python_indirect<T> type;

In C++:

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


struct Foo {
   Foo(int x) : x(x){}
   int get_x() { return x; }
   int x;
};

Foo* make_foo(int x) { return new Foo(x); }

// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
    def("make_foo", make_foo, return_value_policy<manage_new_object>())
    class_<Foo>("Foo")
        .def("get_x", &Foo::get_x)
        ;
}

Python code:

>>> from my_module import *
>>> f = make_foo(3)     # create a Foo object
>>> f.get_x()
3

reference_existing_object is a model of ResultConverterGenerator which can be used to wrap C++ functions which return a reference or pointer to a C++ object. When the wrapped function is called, the value referenced by its return value is not copied. A new Python object is created which contains a pointer to the referent, and no attempt is made to ensure that the lifetime of the referent is at least as long as that of the corresponding Python object. Thus, it can be highly dangerous to use reference_existing_object without additional lifetime management from such models of CallPolicies as with_custodian_and_ward. This class is used in the implementation of return_internal_reference.

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

Requires

T is U& or U* for some U.

Returns

typedef to_python_indirect<T, V> type;, where V is a class whose static execute function constructs an instance holder containing an unowned U* pointing to the referent of the wrapped function's return value.

In C++:

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

// classes to wrap
struct Singleton
{
   Singleton() : x(0) {}

   int exchange(int n)  // set x and return the old value
   {
        std::swap(n, x);
        return n;
   }

   int x;
};

Singleton& get_it()
{
   static Singleton just_one;
   return just_one;
}

// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(singleton)
{
    def("get_it", get_it,
        return_value_policy<reference_existing_object>());

    class_<Singleton>("Singleton")
       .def("exchange", &Singleton::exchange)
       ;
}

Python code:

>>> import singleton
>>> s1 = singleton.get_it()
>>> s2 = singleton.get_it()
>>> id(s1) == id(s2)  # s1 and s2 are not the same object
0
>>> s1.exchange(42)   # but they reference the same C++ Singleton
0
>>> s2.exchange(99)
42

return_by_value is a model of ResultConverterGenerator which can be used to wrap C++ functions returning any reference or value type such that the return value is copied into a new Python object.

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

Returns

typedef to_python_value<T> type;

In C++:

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

// classes to wrap
struct Bar { };

Bar global_bar;

// functions to wrap:
Bar b1();
Bar& b2();
Bar const& b3();

// Wrapper code
using namespace boost::python;
template <class R>
void def_void_function(char const* name, R (*f)())
{
   def(name, f, return_value_policy<return_by_value>());
}

BOOST_PYTHON_MODULE(my_module)
{
    class_<Bar>("Bar");
    def_void_function("b1", b1);
    def_void_function("b2", b2);
    def_void_function("b3", b3);
}

Python code:

>>> from my_module import *
>>> b = b1() # each of these calls
>>> b = b2() # creates a brand
>>> b = b3() # new Bar object

return_opaque_pointer is a model of ResultConverterGenerator which can be used to wrap C++ functions returning pointers to undefined types such that the return value is copied into a new Python object.

In addition to specifying the return_opaque_pointer policy the BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID macro must be used to define specializations for the type_id function on the type pointed to by returned pointer.

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

Returns

detail::opaque_conversion_holder<R> type;

In C++:

# include <boost/python/return_opaque_pointer.hpp>
# include <boost/python/def.hpp>
# include <boost/python/module.hpp>
# include <boost/python/return_value_policy.hpp>

typedef struct opaque_ *opaque;

opaque the_op   = ((opaque) 0x47110815);

opaque get () { return the_op; }
void use (opaque op) {
    if (op != the_op)
	throw std::runtime_error (std::string ("failed"));
}

void failuse (opaque op) {
    if (op == the_op)
	throw std::runtime_error (std::string ("success"));
}

BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)

namespace bpl = boost::python;

BOOST_PYTHON_MODULE(opaque_ext)
{
    bpl::def (
        "get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
    bpl::def ("use", &::use);
    bpl::def ("failuse", &::failuse);
}

Python code:

"""
>>> from opaque_ext import *
>>> #
>>> # Check for correct conversion
>>> use(get())
>>> failuse(get())
Traceback (most recent call last):
        ...
RuntimeError: success
>>> #
>>> # Check that there is no conversion from integers ...
>>> use(0)
Traceback (most recent call last):
        ...
TypeError: bad argument type for built-in operation
>>> #
>>> # ... and from strings to opaque objects
>>> use("")
Traceback (most recent call last):
        ...
TypeError: bad argument type for built-in operation
"""
def run(args = None):
    import sys
    import doctest

    if args is not None:
        sys.argv = args
    return doctest.testmod(sys.modules.get(__name__))

if __name__ == '__main__':
    print "running..."
    import sys
    sys.exit(run()[0])

PrevUpHomeNext