Index: boost/python/return_pointee_value.hpp
===================================================================
--- boost/python/return_pointee_value.hpp (revision 0)
+++ boost/python/return_pointee_value.hpp (revision 0)
@@ -0,0 +1,69 @@
+// Copyright Roman Yakovenko, Maximilian Matthe 2006, 2008.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+/*
+ * Generic return value policy for functions returning pointers which should be
+ * exposed as values. Can be used to return pointers to non-exposed types.
+ *
+ * The code is adapted from
+ * http://mail.python.org/pipermail/c++-sig/2006-November/011568.html .
+ */
+#ifndef RETURN_POINTEE_VALUE_9_11_2006
+#define RETURN_POINTEE_VALUE_9_11_2006
+
+# include
+
+
This return value policy can only be used with types that were exposed with boost.python before.
reference_existing_object
synopsis
+ + |
+
+
+ Boost.Python+ +Header + <boost/python/return_pointee_value.hpp>+ |
+
return_pointee_value
return_pointee_value
synopsisreturn_pointee_value
metafunctionsreturn_pointee_value
return_pointee_value
is a model of ResultConverterGenerator
+ which can be used to wrap C++ functions, that return a pointer to a C++ object. The
+ policy implements the following logic:
+
+
+if return value is NULL pointer: + return None +else: + return bp::object( * return value ) ++ + It passes the value of the pointee to python, thus the conversion for T is used, if + return value is of type T*. +
This return_value_policy can therefore be used to return pointers to python, which + types are not known to boost.python but only a conversion for the pointees. Therefore this + policy should be used to return pointers to objects whose types were wrapped with + other tools, such as SWIG (see example).
+ +Please note: This policy does not take ownership of the wrapped pointer. If the + object pointed to is deleted in C++, the python-object will become invalid too, if your custom + conversion depends on the original object.
+ +return_pointee_value
synopsis+namespace boost { namespace python +{ + struct return_pointee_value + { + template <class T> struct apply; + }; +}} ++ +
return_pointee_value
metafunctions+template <class T> struct apply ++ + + +
Example 1: This example demonstrates the trivial use of return_pointee_value
for returning
+ the value that the returned pointer points to:
+
In C++:
++#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/return_pointee_value.hpp> +#include <boost/python/return_value_policy.hpp> +#inlcude <wxPython.h> +#include <utility> + +// The function which is going to be wrapped: +int* get_value() +{ + static int val = 42; + return &val; +} + +// Function that returns a NULL-Pointer +int* get_null_value() +{ + return NULL; +} + +// The wrapper +BOOST_PYTHON_MODULE(example) +{ + using namespace boost::python; + // Wrap the functions with return_pointee_value + def("get_value", get_value, return_value_policy<return_pointee_value>()); + def("get_null_value", get_null_value, return_value_policy<return_pointee_value>()); +} ++
In Python:
++>>> import example +>>> f = example.get_value() +>>> print f +42 +>>> f = 5 +>>> print example.get_value() +42 +>>> assert None is example.get_null_value() ++
Note that the value of the static C++-variable val
is not changed when python assigns
+ a new value to f
. This is caused by the logic of return_pointee_value
: It returns
+ the boost::python::object
which is constructed from *val
.
Example 2: The following example uses return_pointee_value to return an object that is wrapped + with SWIG. I use the wxPython-API because it's easier to understand.
+ +In C++:
++#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/return_pointee_value.hpp> +#include <boost/python/return_value_policy.hpp> +#inlcude <wxPython.h> +#include <utility> + +// The following code assumes that there is set up a +// working wxWidgets application + +// Function to wrap: +wxWindow* getMainFrame() +{ + return wxGetApp().GetTopWindow(); +} + +// Custom conversion for wxWindow. +struct convert_wxWindow +{ + // Method that does the conversion. Note that it takes a reference to wxWindow, + // not a reference to a pointer. This is needed, because the return value policy + // converts the objects not the pointers. + static PyObject* convert(wxWindow const& o) + { + // Convert the pointer to wxWindow, instead of its value. This is how + // it should be done to convert wxObjects to wxPython. The object will be + // recognized well in python + PyObject* arg = wxPyMake_wxObject(const_cast+ In Python: The example assumes that you call the python function(&o), false); + return arg; + } +}; + +// Wrapper code +using namespace boost::python; +BOOST_PYTHON_MODULE(MyApp) +{ + def("getMainFrame", getMainFrame, return_value_policy ()); + + // register the custom converter + // converter for wxWindow, its conversion_struct, false tells boost that + // we do not have a get_pytype() method in it. + to_python_converter<wxWindow, convert_wxWindow, false>(); +} +
doit
from C++:
++def doit(): + w = MyApp.getMainFrame() + w.Hide() + print "Haha, it's gone!" + w.Show() + return 0 + ++
Note that the returned wxWindow is the same object as the return value of getMainFrame
because of
+the custom construction for boost::python::object
from wxWindow. The conversion just converts the pointer,
+not the object itself.
Revised + + 22 July, 2008 + +
+ +© Copyright Maximilian Matthe, Roman Yakovenko 2006, 2008.
+ + + Index: libs/python/test/return_pointee_value.cpp =================================================================== --- libs/python/test/return_pointee_value.cpp (revision 0) +++ libs/python/test/return_pointee_value.cpp (revision 0) @@ -0,0 +1,55 @@ +// Copyright Maximilian Matthe 2008. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include