1 // Copyright David Abrahams 2002.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 #include <boost/python/handle.hpp>
7 #include <boost/python/type_id.hpp>
8 #include <boost/python/errors.hpp>
9 #include <boost/python/refcount.hpp>
11 #include <boost/python/detail/config.hpp>
12 #include <boost/python/detail/wrap_python.hpp>
14 #include <boost/python/converter/builtin_converters.hpp>
15 #include <boost/python/converter/rvalue_from_python_data.hpp>
16 #include <boost/python/converter/registry.hpp>
17 #include <boost/python/converter/registrations.hpp>
18 #include <boost/python/converter/shared_ptr_deleter.hpp>
19 #include <boost/python/converter/pytype_function.hpp>
21 #include <boost/cast.hpp>
25 namespace boost
{ namespace python
{ namespace converter
{
27 shared_ptr_deleter::shared_ptr_deleter(handle
<> owner
)
31 shared_ptr_deleter::~shared_ptr_deleter() {}
33 void shared_ptr_deleter::operator()(void const*)
41 // An lvalue conversion function which extracts a char const* from a
43 #if PY_VERSION_HEX < 0x03000000
44 void* convert_to_cstring(PyObject
* obj
)
46 return PyString_Check(obj
) ? PyString_AsString(obj
) : 0;
49 void* convert_to_cstring(PyObject
* obj
)
51 return PyUnicode_Check(obj
) ? _PyUnicode_AsString(obj
) : 0;
55 // Given a target type and a SlotPolicy describing how to perform a
56 // given conversion, registers from_python converters which use the
57 // SlotPolicy to extract the type.
58 template <class T
, class SlotPolicy
>
59 struct slot_rvalue_from_python
62 slot_rvalue_from_python()
65 &slot_rvalue_from_python
<T
,SlotPolicy
>::convertible
66 , &slot_rvalue_from_python
<T
,SlotPolicy
>::construct
68 , &SlotPolicy::get_pytype
73 static void* convertible(PyObject
* obj
)
75 unaryfunc
* slot
= SlotPolicy::get_slot(obj
);
76 return slot
&& *slot
? slot
: 0;
79 static void construct(PyObject
* obj
, rvalue_from_python_stage1_data
* data
)
81 // Get the (intermediate) source object
82 unaryfunc creator
= *static_cast<unaryfunc
*>(data
->convertible
);
83 handle
<> intermediate(creator(obj
));
85 // Get the location in which to construct
86 void* storage
= ((rvalue_from_python_storage
<T
>*)data
)->storage
.bytes
;
88 # pragma warning(push)
89 # pragma warning(disable:4244)
91 new (storage
) T( SlotPolicy::extract(intermediate
.get()) );
96 // record successful construction
97 data
->convertible
= storage
;
101 // identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
102 // "slot" which just returns its argument.
103 extern "C" PyObject
* identity_unaryfunc(PyObject
* x
)
108 unaryfunc py_object_identity
= identity_unaryfunc
;
110 #if PY_VERSION_HEX >= 0x03000000
111 // As in Python 3 there is only one integer type, we can have much
113 // XXX(bhy) maybe the code will work with 2.6 or even 2.5?
114 struct int_rvalue_from_python_base
116 static unaryfunc
* get_slot(PyObject
* obj
)
118 return PyLong_Check(obj
) ? &py_object_identity
: 0;
120 static PyTypeObject
const* get_pytype() {return &PyLong_Type
;}
124 struct signed_int_rvalue_from_python
: int_rvalue_from_python_base
126 static T
extract(PyObject
* intermediate
)
128 long x
= PyLong_AsLong(intermediate
);
129 if (PyErr_Occurred())
130 throw_error_already_set();
131 return numeric_cast
<T
>(x
);
136 struct unsigned_int_rvalue_from_python
: int_rvalue_from_python_base
138 static T
extract(PyObject
* intermediate
)
140 unsigned long x
= PyLong_AsUnsignedLong(intermediate
);
141 if (PyErr_Occurred())
142 throw_error_already_set();
143 return numeric_cast
<T
>(x
);
146 #else // PY_VERSION_HEX >= 0x03000000
147 // A SlotPolicy for extracting signed integer types from Python objects
148 struct signed_int_rvalue_from_python_base
150 static unaryfunc
* get_slot(PyObject
* obj
)
152 PyNumberMethods
* number_methods
= obj
->ob_type
->tp_as_number
;
153 if (number_methods
== 0)
157 #if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
158 !PyBool_Check(obj
) &&
160 (PyInt_Check(obj
) || PyLong_Check(obj
)))
162 ? &number_methods
->nb_int
: 0;
164 static PyTypeObject
const* get_pytype() { return &PyInt_Type
;}
168 struct signed_int_rvalue_from_python
: signed_int_rvalue_from_python_base
170 static T
extract(PyObject
* intermediate
)
172 long x
= PyInt_AsLong(intermediate
);
173 if (PyErr_Occurred())
174 throw_error_already_set();
175 return numeric_cast
<T
>(x
);
179 // A SlotPolicy for extracting unsigned integer types from Python objects
180 struct unsigned_int_rvalue_from_python_base
182 static unaryfunc
* get_slot(PyObject
* obj
)
184 PyNumberMethods
* number_methods
= obj
->ob_type
->tp_as_number
;
185 if (number_methods
== 0)
189 #if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
190 !PyBool_Check(obj
) &&
192 (PyInt_Check(obj
) || PyLong_Check(obj
)))
193 ? &py_object_identity
: 0;
195 static PyTypeObject
const* get_pytype() { return &PyInt_Type
;}
199 struct unsigned_int_rvalue_from_python
: unsigned_int_rvalue_from_python_base
201 static T
extract(PyObject
* intermediate
)
203 if (PyLong_Check(intermediate
)) {
204 // PyLong_AsUnsignedLong() checks for negative overflow, so no
205 // need to check it here.
206 unsigned long result
= PyLong_AsUnsignedLong(intermediate
);
207 if (PyErr_Occurred())
208 throw_error_already_set();
209 return numeric_cast
<T
>(result
);
211 // None of PyInt_AsUnsigned*() functions check for negative
212 // overflow, so use PyInt_AS_LONG instead and check if number is
213 // negative, issuing the exception appropriately.
214 long result
= PyInt_AS_LONG(intermediate
);
215 if (PyErr_Occurred())
216 throw_error_already_set();
218 PyErr_SetString(PyExc_OverflowError
, "can't convert negative"
219 " value to unsigned");
220 throw_error_already_set();
222 return numeric_cast
<T
>(result
);
226 #endif // PY_VERSION_HEX >= 0x03000000
228 // Checking Python's macro instead of Boost's - we don't seem to get
229 // the config right all the time. Furthermore, Python's is defined
230 // when long long is absent but __int64 is present.
232 #ifdef HAVE_LONG_LONG
233 // A SlotPolicy for extracting long long types from Python objects
235 struct long_long_rvalue_from_python_base
237 static unaryfunc
* get_slot(PyObject
* obj
)
239 #if PY_VERSION_HEX >= 0x03000000
240 return PyLong_Check(obj
) ? &py_object_identity
: 0;
242 PyNumberMethods
* number_methods
= obj
->ob_type
->tp_as_number
;
243 if (number_methods
== 0)
246 // Return the identity conversion slot to avoid creating a
247 // new object. We'll handle that in the extract function
248 if (PyInt_Check(obj
))
249 return &number_methods
->nb_int
;
250 else if (PyLong_Check(obj
))
251 return &number_methods
->nb_long
;
256 static PyTypeObject
const* get_pytype() { return &PyLong_Type
;}
259 struct long_long_rvalue_from_python
: long_long_rvalue_from_python_base
261 static BOOST_PYTHON_LONG_LONG
extract(PyObject
* intermediate
)
263 #if PY_VERSION_HEX < 0x03000000
264 if (PyInt_Check(intermediate
))
266 return PyInt_AS_LONG(intermediate
);
271 BOOST_PYTHON_LONG_LONG result
= PyLong_AsLongLong(intermediate
);
273 if (PyErr_Occurred())
274 throw_error_already_set();
281 struct unsigned_long_long_rvalue_from_python
: long_long_rvalue_from_python_base
283 static unsigned BOOST_PYTHON_LONG_LONG
extract(PyObject
* intermediate
)
285 #if PY_VERSION_HEX < 0x03000000
286 if (PyInt_Check(intermediate
))
288 return numeric_cast
<unsigned BOOST_PYTHON_LONG_LONG
>(PyInt_AS_LONG(intermediate
));
293 unsigned BOOST_PYTHON_LONG_LONG result
= PyLong_AsUnsignedLongLong(intermediate
);
295 if (PyErr_Occurred())
296 throw_error_already_set();
304 // A SlotPolicy for extracting bool from a Python object
305 struct bool_rvalue_from_python
307 static unaryfunc
* get_slot(PyObject
* obj
)
309 #if PY_VERSION_HEX >= 0x03000000
310 return obj
== Py_None
|| PyLong_Check(obj
) ? &py_object_identity
: 0;
311 #elif PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
312 return obj
== Py_None
|| PyBool_Check(obj
) ? &py_object_identity
: 0;
314 return obj
== Py_None
|| PyInt_Check(obj
) ? &py_object_identity
: 0;
318 static bool extract(PyObject
* intermediate
)
320 return PyObject_IsTrue(intermediate
);
323 static PyTypeObject
const* get_pytype()
325 #if PY_VERSION_HEX >= 0x02030000
333 // A SlotPolicy for extracting floating types from Python objects.
334 struct float_rvalue_from_python
336 static unaryfunc
* get_slot(PyObject
* obj
)
338 PyNumberMethods
* number_methods
= obj
->ob_type
->tp_as_number
;
339 if (number_methods
== 0)
342 // For integer types, return the tp_int conversion slot to avoid
343 // creating a new object. We'll handle that below
344 #if PY_VERSION_HEX < 0x03000000
345 if (PyInt_Check(obj
))
346 return &number_methods
->nb_int
;
349 return (PyLong_Check(obj
) || PyFloat_Check(obj
))
350 ? &number_methods
->nb_float
: 0;
353 static double extract(PyObject
* intermediate
)
355 #if PY_VERSION_HEX < 0x03000000
356 if (PyInt_Check(intermediate
))
358 return PyInt_AS_LONG(intermediate
);
363 return PyFloat_AS_DOUBLE(intermediate
);
366 static PyTypeObject
const* get_pytype() { return &PyFloat_Type
;}
369 #if PY_VERSION_HEX >= 0x03000000
370 unaryfunc py_unicode_as_string_unaryfunc
= PyUnicode_AsUTF8String
;
373 // A SlotPolicy for extracting C++ strings from Python objects.
374 struct string_rvalue_from_python
376 // If the underlying object is "string-able" this will succeed
377 static unaryfunc
* get_slot(PyObject
* obj
)
379 #if PY_VERSION_HEX >= 0x03000000
380 return (PyUnicode_Check(obj
)) ? &py_unicode_as_string_unaryfunc
:
381 PyBytes_Check(obj
) ? &py_object_identity
: 0;
383 return (PyString_Check(obj
)) ? &obj
->ob_type
->tp_str
: 0;
388 // Remember that this will be used to construct the result object
389 #if PY_VERSION_HEX >= 0x03000000
390 static std::string
extract(PyObject
* intermediate
)
392 return std::string(PyBytes_AsString(intermediate
),PyBytes_Size(intermediate
));
394 static PyTypeObject
const* get_pytype() { return &PyUnicode_Type
;}
396 static std::string
extract(PyObject
* intermediate
)
398 return std::string(PyString_AsString(intermediate
),PyString_Size(intermediate
));
400 static PyTypeObject
const* get_pytype() { return &PyString_Type
;}
404 #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
405 // encode_string_unaryfunc/py_encode_string -- manufacture a unaryfunc
406 // "slot" which encodes a Python string using the default encoding
407 extern "C" PyObject
* encode_string_unaryfunc(PyObject
* x
)
409 return PyUnicode_FromEncodedObject( x
, 0, 0 );
411 unaryfunc py_encode_string
= encode_string_unaryfunc
;
413 // A SlotPolicy for extracting C++ strings from Python objects.
414 struct wstring_rvalue_from_python
416 // If the underlying object is "string-able" this will succeed
417 static unaryfunc
* get_slot(PyObject
* obj
)
419 return PyUnicode_Check(obj
)
420 ? &py_object_identity
421 #if PY_VERSION_HEX >= 0x03000000
424 : PyString_Check(obj
)
430 // Remember that this will be used to construct the result object
431 static std::wstring
extract(PyObject
* intermediate
)
433 std::wstring
result(::PyObject_Length(intermediate
), L
' ');
436 int err
= PyUnicode_AsWideChar(
437 #if PY_VERSION_HEX < 0x03020000
445 throw_error_already_set();
449 static PyTypeObject
const* get_pytype() { return &PyUnicode_Type
;}
453 struct complex_rvalue_from_python
455 static unaryfunc
* get_slot(PyObject
* obj
)
457 if (PyComplex_Check(obj
))
458 return &py_object_identity
;
460 return float_rvalue_from_python::get_slot(obj
);
463 static std::complex<double> extract(PyObject
* intermediate
)
465 if (PyComplex_Check(intermediate
))
467 return std::complex<double>(
468 PyComplex_RealAsDouble(intermediate
)
469 , PyComplex_ImagAsDouble(intermediate
));
471 #if PY_VERSION_HEX < 0x03000000
472 else if (PyInt_Check(intermediate
))
474 return PyInt_AS_LONG(intermediate
);
479 return PyFloat_AS_DOUBLE(intermediate
);
482 static PyTypeObject
const* get_pytype() { return &PyComplex_Type
;}
486 BOOST_PYTHON_DECL PyObject
* do_return_to_python(char x
)
488 #if PY_VERSION_HEX >= 0x03000000
489 return PyUnicode_FromStringAndSize(&x
, 1);
491 return PyString_FromStringAndSize(&x
, 1);
495 BOOST_PYTHON_DECL PyObject
* do_return_to_python(char const* x
)
497 #if PY_VERSION_HEX >= 0x03000000
498 return x
? PyUnicode_FromString(x
) : boost::python::detail::none();
500 return x
? PyString_FromString(x
) : boost::python::detail::none();
504 BOOST_PYTHON_DECL PyObject
* do_return_to_python(PyObject
* x
)
506 return x
? x
: boost::python::detail::none();
509 BOOST_PYTHON_DECL PyObject
* do_arg_to_python(PyObject
* x
)
512 return boost::python::detail::none();
518 #define REGISTER_INT_CONVERTERS(signedness, U) \
519 slot_rvalue_from_python< \
521 ,signedness##_int_rvalue_from_python<signedness U> \
524 #define REGISTER_INT_CONVERTERS2(U) \
525 REGISTER_INT_CONVERTERS(signed, U); \
526 REGISTER_INT_CONVERTERS(unsigned, U)
528 void initialize_builtin_converters()
531 slot_rvalue_from_python
<bool,bool_rvalue_from_python
>();
534 REGISTER_INT_CONVERTERS2(char);
535 REGISTER_INT_CONVERTERS2(short);
536 REGISTER_INT_CONVERTERS2(int);
537 REGISTER_INT_CONVERTERS2(long);
539 // using Python's macro instead of Boost's - we don't seem to get the
540 // config right all the time.
541 # ifdef HAVE_LONG_LONG
542 slot_rvalue_from_python
<signed BOOST_PYTHON_LONG_LONG
,long_long_rvalue_from_python
>();
543 slot_rvalue_from_python
<unsigned BOOST_PYTHON_LONG_LONG
,unsigned_long_long_rvalue_from_python
>();
547 slot_rvalue_from_python
<float,float_rvalue_from_python
>();
548 slot_rvalue_from_python
<double,float_rvalue_from_python
>();
549 slot_rvalue_from_python
<long double,float_rvalue_from_python
>();
551 slot_rvalue_from_python
<std::complex<float>,complex_rvalue_from_python
>();
552 slot_rvalue_from_python
<std::complex<double>,complex_rvalue_from_python
>();
553 slot_rvalue_from_python
<std::complex<long double>,complex_rvalue_from_python
>();
555 // Add an lvalue converter for char which gets us char const*
556 #if PY_VERSION_HEX < 0x03000000
557 registry::insert(convert_to_cstring
,type_id
<char>(),&converter::wrap_pytype
<&PyString_Type
>::get_pytype
);
559 registry::insert(convert_to_cstring
,type_id
<char>(),&converter::wrap_pytype
<&PyUnicode_Type
>::get_pytype
);
562 // Register by-value converters to std::string, std::wstring
563 #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
564 slot_rvalue_from_python
<std::wstring
, wstring_rvalue_from_python
>();
566 slot_rvalue_from_python
<std::string
, string_rvalue_from_python
>();
570 }}} // namespace boost::python::converter