88#include < boost/python/converter/registrations.hpp>
99#include < boost/python/converter/rvalue_from_python_data.hpp>
1010#include < boost/python/handle.hpp>
11+ #include < boost/python/detail/raw_pyobject.hpp>
1112#include < vector>
1213#include < algorithm>
1314
1415namespace boost { namespace python { namespace converter {
1516
17+ // rvalue_from_python_stage1 -- do the first stage of a conversion
18+ // from a Python object to a C++ rvalue.
19+ //
20+ // source - the Python object to be converted
21+ // converters - the registry entry for the target type T
22+ //
23+ // Postcondition: where x is the result, one of:
24+ //
25+ // 1. x.convertible == 0, indicating failure
26+ //
27+ // 2. x.construct == 0, x.convertible is the address of an object of
28+ // type T. Indicates a successful lvalue conversion
29+ //
30+ // 3. where y is of type rvalue_from_python_data<T>,
31+ // x.construct(source, y) attempts to construct an object of type T
32+ // in y. Indicates an rvalue converter was found
1633BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1 (
1734 PyObject* source
1835 , registration const & converters)
@@ -34,20 +51,36 @@ BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1(
3451 return data;
3552}
3653
37- BOOST_PYTHON_DECL void * rvalue_from_python_stage2 (
38- PyObject* src, rvalue_from_python_stage1_data& data, void * storage)
54+ // rvalue_result_from_python -- return the address of a C++ object which
55+ // can be used as the result of calling a Python function.
56+ //
57+ // src - the Python object to be converted
58+ //
59+ // data - a reference to the base part of a
60+ // rvalue_from_python_data<T> object, where T is the
61+ // target type of the conversion.
62+ //
63+ // Requires: data.convertible == ®istered<T>::converters
64+ //
65+ BOOST_PYTHON_DECL void * rvalue_result_from_python (
66+ PyObject* src, rvalue_from_python_stage1_data& data)
3967{
68+ // Take possession of the source object.
4069 handle<> holder (src);
4170
71+ // Retrieve the registration
72+ // Cast in two steps for less-capable compilers
4273 void const * converters_ = data.convertible ;
4374 registration const & converters = *static_cast <registration const *>(converters_);
75+
76+ // Look for an eligible converter
4477 data = rvalue_from_python_stage1 (src, converters);
4578
4679 if (!data.convertible )
4780 {
4881 handle<> msg (
4982 ::PyString_FromFormat (
50- " No registered converter was able to produce a C++ lvalue of type %s from this Python object of type %s"
83+ " No registered converter was able to produce a C++ rvalue of type %s from this Python object of type %s"
5184 , converters.target_type.name()
5285 , src->ob_type->tp_name
5386 ));
@@ -130,7 +163,7 @@ BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain(
130163 return chain;
131164}
132165
133- BOOST_PYTHON_DECL void * reference_from_python (
166+ BOOST_PYTHON_DECL void * reference_result_from_python (
134167 PyObject* source
135168 , registration const & converters)
136169{
@@ -163,7 +196,7 @@ BOOST_PYTHON_DECL void* reference_from_python(
163196 return result;
164197}
165198
166- BOOST_PYTHON_DECL void * pointer_from_python (
199+ BOOST_PYTHON_DECL void * pointer_result_from_python (
167200 PyObject* source
168201 , registration const & converters)
169202{
@@ -172,7 +205,7 @@ BOOST_PYTHON_DECL void* pointer_from_python(
172205 Py_DECREF (source);
173206 return 0 ;
174207 }
175- return reference_from_python (source, converters);
208+ return reference_result_from_python (source, converters);
176209}
177210
178211BOOST_PYTHON_DECL void throw_no_class_registered ()
@@ -183,9 +216,27 @@ BOOST_PYTHON_DECL void throw_no_class_registered()
183216 throw_error_already_set ();
184217}
185218
186- BOOST_PYTHON_DECL void void_from_python (PyObject* o)
219+ BOOST_PYTHON_DECL void void_result_from_python (PyObject* o)
187220{
188221 Py_DECREF (expect_non_null (o));
189222}
190223
224+ BOOST_PYTHON_DECL python::detail::new_reference
225+ pytype_result_from_python (PyTypeObject* type, PyObject* source)
226+ {
227+ if (!PyType_IsSubtype (source->ob_type , type))
228+ {
229+ handle<> keeper (source);
230+ handle<> msg (
231+ ::PyString_FromFormat (
232+ " Expecting a Python %s return type, but got an object of type %s instead"
233+ , type
234+ , source->ob_type->tp_name
235+ ));
236+ PyErr_SetObject (PyExc_TypeError, msg.get ());
237+ throw_error_already_set ();
238+ }
239+ return python::detail::new_reference (source);
240+ }
241+
191242}}} // namespace boost::python::converter
0 commit comments