Ticket #3654: bug.cc

File bug.cc, 2.5 KB (added by John Wiegley <jwiegley@…>, 13 years ago)

Simple case that demonstrates the issue

Line 
1#include <boost/optional.hpp>
2#include <boost/python.hpp>
3#include <boost/python/detail/wrap_python.hpp>
4#include <string>
5
6template <typename T, typename TfromPy>
7struct object_from_python
8{
9 object_from_python() {
10 boost::python::converter::registry::insert
11 (&TfromPy::convertible, &TfromPy::construct,
12 boost::python::type_id<T>());
13 }
14};
15
16template <typename T, typename TtoPy, typename TfromPy>
17struct register_python_conversion
18{
19 register_python_conversion() {
20 boost::python::to_python_converter<T, TtoPy>();
21 object_from_python<T, TfromPy>();
22 }
23};
24
25template <typename T>
26struct register_optional_to_python : public boost::noncopyable
27{
28 struct optional_to_python
29 {
30 static PyObject * convert(const boost::optional<T>& value)
31 {
32 return boost::python::incref
33 (value ? boost::python::to_python_value<T>()(*value) :
34 boost::python::detail::none());
35 }
36 };
37
38 struct optional_from_python
39 {
40 static void * convertible(PyObject * source)
41 {
42 using namespace boost::python::converter;
43
44 if (source == Py_None)
45 return source;
46
47 const registration& converters(registered<T>::converters);
48
49 if (implicit_rvalue_convertible_from_python(source, converters)) {
50 rvalue_from_python_stage1_data data =
51 rvalue_from_python_stage1(source, converters);
52 return rvalue_from_python_stage2(source, data, converters);
53 }
54 return NULL;
55 }
56
57 static void construct(PyObject * source,
58 boost::python::converter::rvalue_from_python_stage1_data * data)
59 {
60 using namespace boost::python::converter;
61
62 void * const storage =
63 reinterpret_cast<rvalue_from_python_storage<T> *>(data)->storage.bytes;
64
65 if (data->convertible == source) // == None
66 new (storage) boost::optional<T>(); // A Boost uninitialized value
67 else
68 new (storage) boost::optional<T>(*reinterpret_cast<T *>(data->convertible));
69
70 data->convertible = storage;
71 }
72 };
73
74 explicit register_optional_to_python() {
75 register_python_conversion<boost::optional<T>,
76 optional_to_python, optional_from_python>();
77 }
78};
79
80class amount_t
81{
82public:
83 std::string hello() { return "Hello, world!"; }
84};
85
86class annotation_t
87{
88public:
89 boost::optional<amount_t> price;
90};
91
92boost::optional<amount_t> py_price(annotation_t& ann) {
93 return ann.price;
94}
95
96BOOST_PYTHON_MODULE(bug)
97{
98 using namespace boost::python;
99
100 class_< annotation_t > ("Annotation")
101 .add_property("price", make_getter(&annotation_t::price))
102 .add_property("price2", py_price)
103 ;
104
105 register_optional_to_python<amount_t>();
106}