lvalue_from_pytype.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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)
  5. #ifndef LVALUE_FROM_PYTYPE_DWA2002130_HPP
  6. # define LVALUE_FROM_PYTYPE_DWA2002130_HPP
  7. # include <boost/python/detail/prefix.hpp>
  8. #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
  9. # include <boost/python/converter/pytype_function.hpp>
  10. #endif
  11. # include <boost/python/type_id.hpp>
  12. # include <boost/python/converter/registry.hpp>
  13. # include <boost/python/detail/void_ptr.hpp>
  14. # include <boost/python/detail/type_traits.hpp>
  15. namespace boost { namespace python {
  16. namespace detail
  17. {
  18. // Given a pointer-to-function of 1 parameter returning a reference
  19. // type, return the type_id of the function's return type.
  20. template <class T, class U>
  21. inline type_info extractor_type_id(T&(*)(U))
  22. {
  23. return type_id<T>();
  24. }
  25. // A function generator whose static execute() function is an lvalue
  26. // from_python converter using the given Extractor. U is expected to
  27. // be the actual type of the PyObject instance from which the result
  28. // is being extracted.
  29. template <class Extractor, class U>
  30. struct normalized_extractor
  31. {
  32. static inline void* execute(PyObject* op)
  33. {
  34. typedef typename add_lvalue_reference<U>::type param;
  35. return &Extractor::execute(
  36. boost::python::detail::void_ptr_to_reference(
  37. op, (param(*)())0 )
  38. );
  39. }
  40. };
  41. // Given an Extractor type and a pointer to its execute function,
  42. // return a new object whose static execute function does the same
  43. // job but is a conforming lvalue from_python conversion function.
  44. //
  45. // usage: normalize<Extractor>(&Extractor::execute)
  46. template <class Extractor, class T, class U>
  47. inline normalized_extractor<Extractor,U>
  48. normalize(T(*)(U), Extractor* = 0)
  49. {
  50. return normalized_extractor<Extractor, U>();
  51. }
  52. }
  53. // An Extractor which extracts the given member from a Python object
  54. // whose instances are stored as InstanceType.
  55. template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
  56. struct extract_member
  57. {
  58. static MemberType& execute(InstanceType& c)
  59. {
  60. (void)Py_TYPE(&c); // static assertion
  61. return c.*member;
  62. }
  63. };
  64. // An Extractor which simply extracts the entire python object
  65. // instance of InstanceType.
  66. template <class InstanceType>
  67. struct extract_identity
  68. {
  69. static InstanceType& execute(InstanceType& c)
  70. {
  71. (void)Py_TYPE(&c); // static assertion
  72. return c;
  73. }
  74. };
  75. // Registers a from_python conversion which extracts lvalues using
  76. // Extractor's static execute function from Python objects whose type
  77. // object is python_type.
  78. template <class Extractor, PyTypeObject const* python_type>
  79. struct lvalue_from_pytype
  80. {
  81. lvalue_from_pytype()
  82. {
  83. converter::registry::insert
  84. ( &extract
  85. , detail::extractor_type_id(&Extractor::execute)
  86. #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
  87. , &get_pytype
  88. #endif
  89. );
  90. }
  91. private:
  92. static void* extract(PyObject* op)
  93. {
  94. return PyObject_TypeCheck(op, const_cast<PyTypeObject*>(python_type))
  95. ? const_cast<void*>(
  96. static_cast<void const volatile*>(
  97. detail::normalize<Extractor>(&Extractor::execute).execute(op)))
  98. : 0
  99. ;
  100. }
  101. #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
  102. static PyTypeObject const*get_pytype() { return python_type; }
  103. #endif
  104. };
  105. }} // namespace boost::python
  106. #endif // LVALUE_FROM_PYTYPE_DWA2002130_HPP