extract.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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 EXTRACT_DWA200265_HPP
  6. # define EXTRACT_DWA200265_HPP
  7. # include <boost/python/detail/prefix.hpp>
  8. # include <boost/python/converter/object_manager.hpp>
  9. # include <boost/python/converter/from_python.hpp>
  10. # include <boost/python/converter/rvalue_from_python_data.hpp>
  11. # include <boost/python/converter/registered.hpp>
  12. # include <boost/python/converter/registered_pointee.hpp>
  13. # include <boost/python/object_core.hpp>
  14. # include <boost/python/refcount.hpp>
  15. # include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
  16. # include <boost/python/detail/void_ptr.hpp>
  17. # include <boost/python/detail/void_return.hpp>
  18. # include <boost/utility.hpp>
  19. # include <boost/call_traits.hpp>
  20. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 900)
  21. // workaround for VC++ 6.x or 7.0
  22. # define BOOST_EXTRACT_WORKAROUND ()
  23. #else
  24. # define BOOST_EXTRACT_WORKAROUND
  25. #endif
  26. namespace boost { namespace python {
  27. namespace api
  28. {
  29. class object;
  30. }
  31. namespace converter
  32. {
  33. template <class Ptr>
  34. struct extract_pointer
  35. {
  36. typedef Ptr result_type;
  37. extract_pointer(PyObject*);
  38. bool check() const;
  39. Ptr operator()() const;
  40. private:
  41. PyObject* m_source;
  42. void* m_result;
  43. };
  44. template <class Ref>
  45. struct extract_reference
  46. {
  47. typedef Ref result_type;
  48. extract_reference(PyObject*);
  49. bool check() const;
  50. Ref operator()() const;
  51. private:
  52. PyObject* m_source;
  53. void* m_result;
  54. };
  55. template <class T>
  56. struct extract_rvalue : private noncopyable
  57. {
  58. typedef typename mpl::if_<
  59. python::detail::copy_ctor_mutates_rhs<T>
  60. , T&
  61. , typename call_traits<T>::param_type
  62. >::type result_type;
  63. extract_rvalue(PyObject*);
  64. bool check() const;
  65. result_type operator()() const;
  66. private:
  67. PyObject* m_source;
  68. mutable rvalue_from_python_data<T> m_data;
  69. };
  70. template <class T>
  71. struct extract_object_manager
  72. {
  73. typedef T result_type;
  74. extract_object_manager(PyObject*);
  75. bool check() const;
  76. result_type operator()() const;
  77. private:
  78. PyObject* m_source;
  79. };
  80. template <class T>
  81. struct select_extract
  82. {
  83. BOOST_STATIC_CONSTANT(
  84. bool, obj_mgr = is_object_manager<T>::value);
  85. BOOST_STATIC_CONSTANT(
  86. bool, ptr = is_pointer<T>::value);
  87. BOOST_STATIC_CONSTANT(
  88. bool, ref = is_reference<T>::value);
  89. typedef typename mpl::if_c<
  90. obj_mgr
  91. , extract_object_manager<T>
  92. , typename mpl::if_c<
  93. ptr
  94. , extract_pointer<T>
  95. , typename mpl::if_c<
  96. ref
  97. , extract_reference<T>
  98. , extract_rvalue<T>
  99. >::type
  100. >::type
  101. >::type type;
  102. };
  103. }
  104. template <class T>
  105. struct extract
  106. : converter::select_extract<T>::type
  107. {
  108. private:
  109. typedef typename converter::select_extract<T>::type base;
  110. public:
  111. typedef typename base::result_type result_type;
  112. operator result_type() const
  113. {
  114. return (*this)();
  115. }
  116. extract(PyObject*);
  117. extract(api::object const&);
  118. };
  119. //
  120. // Implementations
  121. //
  122. template <class T>
  123. inline extract<T>::extract(PyObject* o)
  124. : base(o)
  125. {
  126. }
  127. template <class T>
  128. inline extract<T>::extract(api::object const& o)
  129. : base(o.ptr())
  130. {
  131. }
  132. namespace converter
  133. {
  134. template <class T>
  135. inline extract_rvalue<T>::extract_rvalue(PyObject* x)
  136. : m_source(x)
  137. , m_data(
  138. (rvalue_from_python_stage1)(x, registered<T>::converters)
  139. )
  140. {
  141. }
  142. template <class T>
  143. inline bool
  144. extract_rvalue<T>::check() const
  145. {
  146. return m_data.stage1.convertible;
  147. }
  148. template <class T>
  149. inline typename extract_rvalue<T>::result_type
  150. extract_rvalue<T>::operator()() const
  151. {
  152. return *(T*)(
  153. // Only do the stage2 conversion once
  154. m_data.stage1.convertible == m_data.storage.bytes
  155. ? m_data.storage.bytes
  156. : (rvalue_from_python_stage2)(m_source, m_data.stage1, registered<T>::converters)
  157. );
  158. }
  159. template <class Ref>
  160. inline extract_reference<Ref>::extract_reference(PyObject* obj)
  161. : m_source(obj)
  162. , m_result(
  163. (get_lvalue_from_python)(obj, registered<Ref>::converters)
  164. )
  165. {
  166. }
  167. template <class Ref>
  168. inline bool extract_reference<Ref>::check() const
  169. {
  170. return m_result != 0;
  171. }
  172. template <class Ref>
  173. inline Ref extract_reference<Ref>::operator()() const
  174. {
  175. if (m_result == 0)
  176. (throw_no_reference_from_python)(m_source, registered<Ref>::converters);
  177. return python::detail::void_ptr_to_reference(m_result, (Ref(*)())0);
  178. }
  179. template <class Ptr>
  180. inline extract_pointer<Ptr>::extract_pointer(PyObject* obj)
  181. : m_source(obj)
  182. , m_result(
  183. obj == Py_None ? 0 : (get_lvalue_from_python)(obj, registered_pointee<Ptr>::converters)
  184. )
  185. {
  186. }
  187. template <class Ptr>
  188. inline bool extract_pointer<Ptr>::check() const
  189. {
  190. return m_source == Py_None || m_result != 0;
  191. }
  192. template <class Ptr>
  193. inline Ptr extract_pointer<Ptr>::operator()() const
  194. {
  195. if (m_result == 0 && m_source != Py_None)
  196. (throw_no_pointer_from_python)(m_source, registered_pointee<Ptr>::converters);
  197. return Ptr(m_result);
  198. }
  199. template <class T>
  200. inline extract_object_manager<T>::extract_object_manager(PyObject* obj)
  201. : m_source(obj)
  202. {
  203. }
  204. template <class T>
  205. inline bool extract_object_manager<T>::check() const
  206. {
  207. return object_manager_traits<T>::check(m_source);
  208. }
  209. template <class T>
  210. inline T extract_object_manager<T>::operator()() const
  211. {
  212. return T(
  213. object_manager_traits<T>::adopt(python::incref(m_source))
  214. );
  215. }
  216. }
  217. }} // namespace boost::python::converter
  218. #endif // EXTRACT_DWA200265_HPP