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 + -
显示快捷键?