builtin_converters.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 442 行
CPP
442 行
// Copyright David Abrahams 2002.// 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 <boost/python/handle.hpp>#include <boost/python/type_id.hpp>#include <boost/python/errors.hpp>#include <boost/python/refcount.hpp>#include <boost/python/detail/config.hpp>#include <boost/python/detail/wrap_python.hpp>#include <boost/python/converter/builtin_converters.hpp>#include <boost/python/converter/rvalue_from_python_data.hpp>#include <boost/python/converter/registry.hpp>#include <boost/python/converter/registrations.hpp>#include <boost/python/converter/shared_ptr_deleter.hpp>#include <boost/python/converter/pytype_function.hpp>#include <boost/cast.hpp>#include <string>#include <complex>namespace boost { namespace python { namespace converter {shared_ptr_deleter::shared_ptr_deleter(handle<> owner) : owner(owner){}shared_ptr_deleter::~shared_ptr_deleter() {}void shared_ptr_deleter::operator()(void const*){ owner.reset();}namespace{ // An lvalue conversion function which extracts a char const* from a // Python String. void* convert_to_cstring(PyObject* obj) { return PyString_Check(obj) ? PyString_AsString(obj) : 0; } // Given a target type and a SlotPolicy describing how to perform a // given conversion, registers from_python converters which use the // SlotPolicy to extract the type. template <class T, class SlotPolicy> struct slot_rvalue_from_python { public: slot_rvalue_from_python() { registry::insert( &slot_rvalue_from_python<T,SlotPolicy>::convertible , &slot_rvalue_from_python<T,SlotPolicy>::construct , type_id<T>() , &SlotPolicy::get_pytype ); } private: static void* convertible(PyObject* obj) { unaryfunc* slot = SlotPolicy::get_slot(obj); return slot && *slot ? slot : 0; } static void construct(PyObject* obj, rvalue_from_python_stage1_data* data) { // Get the (intermediate) source object unaryfunc creator = *static_cast<unaryfunc*>(data->convertible); handle<> intermediate(creator(obj)); // Get the location in which to construct void* storage = ((rvalue_from_python_storage<T>*)data)->storage.bytes;# ifdef _MSC_VER# pragma warning(push)# pragma warning(disable:4244)# endif new (storage) T( SlotPolicy::extract(intermediate.get()) ); # ifdef _MSC_VER# pragma warning(pop)# endif // record successful construction data->convertible = storage; } }; // A SlotPolicy for extracting signed integer types from Python objects struct signed_int_rvalue_from_python_base { static unaryfunc* get_slot(PyObject* obj) { PyNumberMethods* number_methods = obj->ob_type->tp_as_number; if (number_methods == 0) return 0; return (PyInt_Check(obj) || PyLong_Check(obj)) ? &number_methods->nb_int : 0; } static PyTypeObject const* get_pytype() { return &PyInt_Type;} }; template <class T> struct signed_int_rvalue_from_python : signed_int_rvalue_from_python_base { static T extract(PyObject* intermediate) { long x = PyInt_AsLong(intermediate); if (PyErr_Occurred()) throw_error_already_set(); return numeric_cast<T>(x); } }; // identity_unaryfunc/py_object_identity -- manufacture a unaryfunc // "slot" which just returns its argument. extern "C" PyObject* identity_unaryfunc(PyObject* x) { Py_INCREF(x); return x; } unaryfunc py_object_identity = identity_unaryfunc; // A SlotPolicy for extracting unsigned integer types from Python objects struct unsigned_int_rvalue_from_python_base { static unaryfunc* get_slot(PyObject* obj) { PyNumberMethods* number_methods = obj->ob_type->tp_as_number; if (number_methods == 0) return 0; return (PyInt_Check(obj) || PyLong_Check(obj)) ? &py_object_identity : 0; } static PyTypeObject const* get_pytype() { return &PyInt_Type;} }; template <class T> struct unsigned_int_rvalue_from_python : unsigned_int_rvalue_from_python_base { static T extract(PyObject* intermediate) { return numeric_cast<T>( PyLong_Check(intermediate) ? PyLong_AsUnsignedLong(intermediate) : PyInt_AS_LONG(intermediate)); } };// Checking Python's macro instead of Boost's - we don't seem to get// the config right all the time. Furthermore, Python's is defined// when long long is absent but __int64 is present. #ifdef HAVE_LONG_LONG // A SlotPolicy for extracting long long types from Python objects struct long_long_rvalue_from_python_base { static unaryfunc* get_slot(PyObject* obj) { PyNumberMethods* number_methods = obj->ob_type->tp_as_number; if (number_methods == 0) return 0; // Return the identity conversion slot to avoid creating a // new object. We'll handle that in the extract function if (PyInt_Check(obj)) return &number_methods->nb_int; else if (PyLong_Check(obj)) return &number_methods->nb_long; else return 0; } static PyTypeObject const* get_pytype() { return &PyInt_Type;} }; struct long_long_rvalue_from_python : long_long_rvalue_from_python_base { static BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate) { if (PyInt_Check(intermediate)) { return PyInt_AS_LONG(intermediate); } else { BOOST_PYTHON_LONG_LONG result = PyLong_AsLongLong(intermediate); if (PyErr_Occurred()) throw_error_already_set(); return result; } } }; struct unsigned_long_long_rvalue_from_python : long_long_rvalue_from_python_base { static unsigned BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate) { if (PyInt_Check(intermediate)) { return numeric_cast<unsigned BOOST_PYTHON_LONG_LONG>(PyInt_AS_LONG(intermediate)); } else { unsigned BOOST_PYTHON_LONG_LONG result = PyLong_AsUnsignedLongLong(intermediate); if (PyErr_Occurred()) throw_error_already_set(); return result; } } };#endif // A SlotPolicy for extracting bool from a Python object struct bool_rvalue_from_python { static unaryfunc* get_slot(PyObject* obj) { return obj == Py_None || PyInt_Check(obj) ? &py_object_identity : 0; } static bool extract(PyObject* intermediate) { return PyObject_IsTrue(intermediate); } static PyTypeObject const* get_pytype() {#if PY_VERSION_HEX >= 0x02030000 return &PyBool_Type;#else return &PyInt_Type;#endif } }; // A SlotPolicy for extracting floating types from Python objects. struct float_rvalue_from_python { static unaryfunc* get_slot(PyObject* obj) { PyNumberMethods* number_methods = obj->ob_type->tp_as_number; if (number_methods == 0) return 0; // For integer types, return the tp_int conversion slot to avoid // creating a new object. We'll handle that below if (PyInt_Check(obj)) return &number_methods->nb_int; return (PyLong_Check(obj) || PyFloat_Check(obj)) ? &number_methods->nb_float : 0; } static double extract(PyObject* intermediate) { if (PyInt_Check(intermediate)) { return PyInt_AS_LONG(intermediate); } else { return PyFloat_AS_DOUBLE(intermediate); } } static PyTypeObject const* get_pytype() { return &PyFloat_Type;} }; // A SlotPolicy for extracting C++ strings from Python objects. struct string_rvalue_from_python { // If the underlying object is "string-able" this will succeed static unaryfunc* get_slot(PyObject* obj) { return (PyString_Check(obj)) ? &obj->ob_type->tp_str : 0; }; // Remember that this will be used to construct the result object static std::string extract(PyObject* intermediate) { return std::string(PyString_AsString(intermediate),PyString_Size(intermediate)); } static PyTypeObject const* get_pytype() { return &PyString_Type;} };#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING) // encode_string_unaryfunc/py_encode_string -- manufacture a unaryfunc // "slot" which encodes a Python string using the default encoding extern "C" PyObject* encode_string_unaryfunc(PyObject* x) { return PyUnicode_FromEncodedObject( x, 0, 0 ); } unaryfunc py_encode_string = encode_string_unaryfunc; // A SlotPolicy for extracting C++ strings from Python objects. struct wstring_rvalue_from_python { // If the underlying object is "string-able" this will succeed static unaryfunc* get_slot(PyObject* obj) { return PyUnicode_Check(obj) ? &py_object_identity : PyString_Check(obj) ? &py_encode_string : 0; }; // Remember that this will be used to construct the result object static std::wstring extract(PyObject* intermediate) { std::wstring result(::PyObject_Length(intermediate), L' '); if (!result.empty()) { int err = PyUnicode_AsWideChar( (PyUnicodeObject *)intermediate , &result[0] , result.size()); if (err == -1) throw_error_already_set(); } return result; } static PyTypeObject const* get_pytype() { return &PyUnicode_Type;} };#endif struct complex_rvalue_from_python { static unaryfunc* get_slot(PyObject* obj) { if (PyComplex_Check(obj)) return &py_object_identity; else return float_rvalue_from_python::get_slot(obj); } static std::complex<double> extract(PyObject* intermediate) { if (PyComplex_Check(intermediate)) { return std::complex<double>( PyComplex_RealAsDouble(intermediate) , PyComplex_ImagAsDouble(intermediate)); } else if (PyInt_Check(intermediate)) { return PyInt_AS_LONG(intermediate); } else { return PyFloat_AS_DOUBLE(intermediate); } } static PyTypeObject const* get_pytype() { return &PyComplex_Type;} };} BOOST_PYTHON_DECL PyObject* do_return_to_python(char x){ return PyString_FromStringAndSize(&x, 1);} BOOST_PYTHON_DECL PyObject* do_return_to_python(char const* x){ return x ? PyString_FromString(x) : boost::python::detail::none();} BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject* x){ return x ? x : boost::python::detail::none();} BOOST_PYTHON_DECL PyObject* do_arg_to_python(PyObject* x){ if (x == 0) return boost::python::detail::none(); Py_INCREF(x); return x;}#define REGISTER_INT_CONVERTERS(signedness, U) \ slot_rvalue_from_python< \ signedness U \ ,signedness##_int_rvalue_from_python<signedness U> \ >()#define REGISTER_INT_CONVERTERS2(U) \ REGISTER_INT_CONVERTERS(signed, U); \ REGISTER_INT_CONVERTERS(unsigned, U) void initialize_builtin_converters(){ // booleans slot_rvalue_from_python<bool,bool_rvalue_from_python>(); // integer types REGISTER_INT_CONVERTERS2(char); REGISTER_INT_CONVERTERS2(short); REGISTER_INT_CONVERTERS2(int); REGISTER_INT_CONVERTERS2(long); // using Python's macro instead of Boost's - we don't seem to get the// config right all the time.# ifdef HAVE_LONG_LONG slot_rvalue_from_python<signed BOOST_PYTHON_LONG_LONG,long_long_rvalue_from_python>(); slot_rvalue_from_python<unsigned BOOST_PYTHON_LONG_LONG,unsigned_long_long_rvalue_from_python>();# endif // floating types slot_rvalue_from_python<float,float_rvalue_from_python>(); slot_rvalue_from_python<double,float_rvalue_from_python>(); slot_rvalue_from_python<long double,float_rvalue_from_python>(); slot_rvalue_from_python<std::complex<float>,complex_rvalue_from_python>(); slot_rvalue_from_python<std::complex<double>,complex_rvalue_from_python>(); slot_rvalue_from_python<std::complex<long double>,complex_rvalue_from_python>(); // Add an lvalue converter for char which gets us char const* registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyString_Type>::get_pytype); // Register by-value converters to std::string, std::wstring#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING) slot_rvalue_from_python<std::wstring, wstring_rvalue_from_python>();# endif slot_rvalue_from_python<std::string, string_rvalue_from_python>();}}}} // namespace boost::python::converter
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?