Skip to content

Commit f271726

Browse files
committed
Added reference, deep and shallow pointer to_python conversions
[SVN r13152]
1 parent 22f6612 commit f271726

File tree

4 files changed

+125
-5
lines changed

4 files changed

+125
-5
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright David Abrahams 2002. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
#ifndef POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP
7+
# define POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP
8+
9+
# include <boost/python/detail/wrap_python.hpp>
10+
# include <boost/type_traits/transform_traits.hpp>
11+
# include <boost/type_traits/cv_traits.hpp>
12+
# include <boost/python/converter/type_id.hpp>
13+
# include <boost/python/converter/registry.hpp>
14+
# include <boost/python/converter/to_python_function_type.hpp>
15+
# include <boost/python/converter/pointer_type_id.hpp>
16+
17+
namespace boost { namespace python { namespace converter {
18+
19+
// pointee_to_python_function --
20+
//
21+
// essentially a "templated global reference" which holds the
22+
// converter for converting a type to Python by-value. We "normalize"
23+
// T by adding "const volatile&" so that fewer global variables and
24+
// associated static initializations are generated.
25+
namespace detail
26+
{
27+
template <class T>
28+
struct pointee_to_python_function_base
29+
{
30+
static to_python_function_t const& value;
31+
};
32+
33+
template <class T>
34+
to_python_function_t const&
35+
pointee_to_python_function_base<T>::value
36+
= converter::registry::get_to_python_function(pointer_type_id<T>());
37+
}
38+
39+
template <class T>
40+
struct pointee_to_python_function
41+
: detail::pointee_to_python_function_base<
42+
typename add_reference<
43+
typename add_cv<T>::type
44+
>::type
45+
>
46+
{
47+
};
48+
49+
}}} // namespace boost::python::converter
50+
51+
#endif // POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP

src/converter/callback.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <boost/python/errors.hpp>
99
#include <boost/python/converter/find_from_python.hpp>
1010
#include <boost/python/reference.hpp>
11+
#include <boost/python/detail/none.hpp>
1112

1213
namespace boost { namespace python { namespace converter {
1314

@@ -25,7 +26,10 @@ namespace detail
2526
, const_cast<char*>("no to_python (by-value) converter found for type"));
2627
throw error_already_set();
2728
}
28-
return converter(const_cast<void*>(source));
29+
30+
return source == 0
31+
? python::detail::none()
32+
: converter(const_cast<void*>(source));
2933
}
3034
}
3135

@@ -45,6 +49,14 @@ namespace detail
4549
throw error_already_set();
4650
}
4751
}
52+
53+
BOOST_PYTHON_DECL void throw_no_class_registered()
54+
{
55+
PyErr_SetString(
56+
PyExc_TypeError
57+
, const_cast<char*>("class not registered for to_python type"));
58+
throw error_already_set();
59+
}
4860

4961
BOOST_PYTHON_DECL void* convert_rvalue(PyObject* src, rvalue_stage1_data& data, void* storage)
5062
{

test/callbacks.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <boost/python/returning.hpp>
88
#include <boost/python/class.hpp>
99
#include <boost/ref.hpp>
10+
#include <boost/python/ptr.hpp>
1011

1112
using namespace boost::python;
1213

@@ -42,9 +43,24 @@ X apply_X_X(PyObject* f, X x)
4243
return returning<X>::call(f, x);
4344
}
4445

45-
void apply_void_X_ref(PyObject* f, X x)
46+
void apply_void_X_ref(PyObject* f, X& x)
4647
{
47-
returning<X>::call(f, boost::ref(x));
48+
returning<void>::call(f, boost::ref(x));
49+
}
50+
51+
void apply_void_X_cref(PyObject* f, X const& x)
52+
{
53+
returning<void>::call(f, boost::cref(x));
54+
}
55+
56+
void apply_void_X_ptr(PyObject* f, X* x)
57+
{
58+
returning<void>::call(f, ptr(x));
59+
}
60+
61+
void apply_void_X_deep_ptr(PyObject* f, X* x)
62+
{
63+
returning<void>::call(f, x);
4864
}
4965

5066
int X::counter;
@@ -56,6 +72,9 @@ BOOST_PYTHON_MODULE_INIT(callbacks_ext)
5672
.def("apply_void_int", apply_void_int)
5773
.def("apply_X_X", apply_X_X)
5874
.def("apply_void_X_ref", apply_void_X_ref)
75+
.def("apply_void_X_cref", apply_void_X_cref)
76+
.def("apply_void_X_ptr", apply_void_X_ptr)
77+
.def("apply_void_X_deep_ptr", apply_void_X_deep_ptr)
5978
.add(
6079
class_<X>("X")
6180
.def_init(args<int>())
@@ -67,5 +86,4 @@ BOOST_PYTHON_MODULE_INIT(callbacks_ext)
6786
;
6887
}
6988

70-
71-
89+
#include "module_tail.cpp"

test/callbacks.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,45 @@
2727
>>> apply_void_X_ref(increment, x)
2828
>>> x.value()
2929
43
30+
31+
>>> apply_void_X_cref(increment, x)
32+
>>> x.value() # const-ness is not respected, sorry!
33+
44
34+
35+
>>> last_x = 1
36+
>>> def decrement(x):
37+
... global last_x
38+
... last_x = x
39+
... if x is not None:
40+
... x.set(x.value() - 1)
41+
42+
>>> apply_void_X_ptr(decrement, x)
43+
>>> x.value()
44+
43
45+
>>> last_x.value()
46+
43
47+
>>> increment(last_x)
48+
>>> x.value()
49+
44
50+
>>> last_x.value()
51+
44
52+
53+
>>> apply_void_X_ptr(decrement, None)
54+
>>> assert last_x is None
55+
>>> x.value()
56+
44
57+
58+
>>> last_x = 1
59+
>>> apply_void_X_deep_ptr(decrement, None)
60+
>>> assert last_x is None
61+
>>> x.value()
62+
44
63+
64+
>>> apply_void_X_deep_ptr(decrement, x)
65+
>>> x.value()
66+
44
67+
>>> last_x.value()
68+
43
3069
'''
3170

3271
def run(args = None):

0 commit comments

Comments
 (0)