arg_from_python.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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 ARG_FROM_PYTHON_DWA2002127_HPP
  6. # define ARG_FROM_PYTHON_DWA2002127_HPP
  7. # include <boost/python/detail/prefix.hpp>
  8. # include <boost/python/converter/from_python.hpp>
  9. # include <boost/python/detail/indirect_traits.hpp>
  10. # include <boost/python/detail/type_traits.hpp>
  11. # include <boost/python/converter/rvalue_from_python_data.hpp>
  12. # include <boost/mpl/eval_if.hpp>
  13. # include <boost/mpl/if.hpp>
  14. # include <boost/mpl/identity.hpp>
  15. # include <boost/mpl/and.hpp>
  16. # include <boost/mpl/or.hpp>
  17. # include <boost/mpl/not.hpp>
  18. # include <boost/python/converter/registry.hpp>
  19. # include <boost/python/converter/registered.hpp>
  20. # include <boost/python/converter/registered_pointee.hpp>
  21. # include <boost/python/detail/void_ptr.hpp>
  22. # include <boost/python/back_reference.hpp>
  23. # include <boost/python/detail/referent_storage.hpp>
  24. # include <boost/python/converter/obj_mgr_arg_from_python.hpp>
  25. namespace boost { namespace python
  26. {
  27. template <class T> struct arg_from_python;
  28. }}
  29. // This header defines Python->C++ function argument converters,
  30. // parametrized on the argument type.
  31. namespace boost { namespace python { namespace converter {
  32. //
  33. // lvalue converters
  34. //
  35. // These require that an lvalue of the type U is stored somewhere in
  36. // the Python object being converted.
  37. // Used when T == U*const&
  38. template <class T>
  39. struct pointer_cref_arg_from_python
  40. {
  41. typedef T result_type;
  42. pointer_cref_arg_from_python(PyObject*);
  43. T operator()() const;
  44. bool convertible() const;
  45. private: // storage for a U*
  46. // needed because not all compilers will let us declare U* as the
  47. // return type of operator() -- we return U*const& instead
  48. typename python::detail::referent_storage<T>::type m_result;
  49. };
  50. // Base class for pointer and reference converters
  51. struct arg_lvalue_from_python_base
  52. {
  53. public: // member functions
  54. arg_lvalue_from_python_base(void* result);
  55. bool convertible() const;
  56. protected: // member functions
  57. void*const& result() const;
  58. private: // data members
  59. void* m_result;
  60. };
  61. // Used when T == U*
  62. template <class T>
  63. struct pointer_arg_from_python : arg_lvalue_from_python_base
  64. {
  65. typedef T result_type;
  66. pointer_arg_from_python(PyObject*);
  67. T operator()() const;
  68. };
  69. // Used when T == U& and (T != V const& or T == W volatile&)
  70. template <class T>
  71. struct reference_arg_from_python : arg_lvalue_from_python_base
  72. {
  73. typedef T result_type;
  74. reference_arg_from_python(PyObject*);
  75. T operator()() const;
  76. };
  77. // ===================
  78. //
  79. // rvalue converters
  80. //
  81. // These require only that an object of type T can be created from
  82. // the given Python object, but not that the T object exist
  83. // somewhere in storage.
  84. //
  85. // Used when T is a plain value (non-pointer, non-reference) type or
  86. // a (non-volatile) const reference to a plain value type.
  87. template <class T>
  88. struct arg_rvalue_from_python
  89. {
  90. typedef typename boost::python::detail::add_lvalue_reference<
  91. T
  92. // We can't add_const here, or it would be impossible to pass
  93. // auto_ptr<U> args from Python to C++
  94. >::type result_type;
  95. arg_rvalue_from_python(PyObject*);
  96. bool convertible() const;
  97. # if _MSC_FULL_VER > 13102196
  98. typename arg_rvalue_from_python<T>::
  99. # endif
  100. result_type operator()();
  101. private:
  102. rvalue_from_python_data<result_type> m_data;
  103. PyObject* m_source;
  104. };
  105. // ==================
  106. // Converts to a (PyObject*,T) bundle, for when you need a reference
  107. // back to the Python object
  108. template <class T>
  109. struct back_reference_arg_from_python
  110. : boost::python::arg_from_python<typename T::type>
  111. {
  112. typedef T result_type;
  113. back_reference_arg_from_python(PyObject*);
  114. T operator()();
  115. private:
  116. typedef boost::python::arg_from_python<typename T::type> base;
  117. PyObject* m_source;
  118. };
  119. // ==================
  120. template <class C, class T, class F>
  121. struct if_2
  122. {
  123. typedef typename mpl::eval_if<C, mpl::identity<T>, F>::type type;
  124. };
  125. // This metafunction selects the appropriate arg_from_python converter
  126. // type for an argument of type T.
  127. template <class T>
  128. struct select_arg_from_python
  129. {
  130. typedef typename if_2<
  131. is_object_manager<T>
  132. , object_manager_value_arg_from_python<T>
  133. , if_2<
  134. is_reference_to_object_manager<T>
  135. , object_manager_ref_arg_from_python<T>
  136. , if_2<
  137. is_pointer<T>
  138. , pointer_arg_from_python<T>
  139. , if_2<
  140. mpl::and_<
  141. indirect_traits::is_reference_to_pointer<T>
  142. , indirect_traits::is_reference_to_const<T>
  143. , mpl::not_<indirect_traits::is_reference_to_volatile<T> >
  144. >
  145. , pointer_cref_arg_from_python<T>
  146. , if_2<
  147. mpl::or_<
  148. indirect_traits::is_reference_to_non_const<T>
  149. , indirect_traits::is_reference_to_volatile<T>
  150. >
  151. , reference_arg_from_python<T>
  152. , mpl::if_<
  153. boost::python::is_back_reference<T>
  154. , back_reference_arg_from_python<T>
  155. , arg_rvalue_from_python<T>
  156. >
  157. >
  158. >
  159. >
  160. >
  161. >::type type;
  162. };
  163. // ==================
  164. //
  165. // implementations
  166. //
  167. // arg_lvalue_from_python_base
  168. //
  169. inline arg_lvalue_from_python_base::arg_lvalue_from_python_base(void* result)
  170. : m_result(result)
  171. {
  172. }
  173. inline bool arg_lvalue_from_python_base::convertible() const
  174. {
  175. return m_result != 0;
  176. }
  177. inline void*const& arg_lvalue_from_python_base::result() const
  178. {
  179. return m_result;
  180. }
  181. // pointer_cref_arg_from_python
  182. //
  183. namespace detail
  184. {
  185. // null_ptr_reference -- a function returning a reference to a null
  186. // pointer of type U. Needed so that extractors for T*const& can
  187. // convert Python's None.
  188. template <class T>
  189. struct null_ptr_owner
  190. {
  191. static T value;
  192. };
  193. template <class T> T null_ptr_owner<T>::value = 0;
  194. template <class U>
  195. inline U& null_ptr_reference(U&(*)())
  196. {
  197. return null_ptr_owner<U>::value;
  198. }
  199. }
  200. template <class T>
  201. inline pointer_cref_arg_from_python<T>::pointer_cref_arg_from_python(PyObject* p)
  202. {
  203. // T == U*const&: store a U* in the m_result storage. Nonzero
  204. // indicates success. If find returns nonzero, it's a pointer to
  205. // a U object.
  206. python::detail::write_void_ptr_reference(
  207. m_result.bytes
  208. , p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters)
  209. , (T(*)())0);
  210. }
  211. template <class T>
  212. inline bool pointer_cref_arg_from_python<T>::convertible() const
  213. {
  214. return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0;
  215. }
  216. template <class T>
  217. inline T pointer_cref_arg_from_python<T>::operator()() const
  218. {
  219. return (*(void**)m_result.bytes == Py_None) // None ==> 0
  220. ? detail::null_ptr_reference((T(*)())0)
  221. // Otherwise, return a U*const& to the m_result storage.
  222. : python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0);
  223. }
  224. // pointer_arg_from_python
  225. //
  226. template <class T>
  227. inline pointer_arg_from_python<T>::pointer_arg_from_python(PyObject* p)
  228. : arg_lvalue_from_python_base(
  229. p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters))
  230. {
  231. }
  232. template <class T>
  233. inline T pointer_arg_from_python<T>::operator()() const
  234. {
  235. return (result() == Py_None) ? 0 : T(result());
  236. }
  237. // reference_arg_from_python
  238. //
  239. template <class T>
  240. inline reference_arg_from_python<T>::reference_arg_from_python(PyObject* p)
  241. : arg_lvalue_from_python_base(converter::get_lvalue_from_python(p,registered<T>::converters))
  242. {
  243. }
  244. template <class T>
  245. inline T reference_arg_from_python<T>::operator()() const
  246. {
  247. return python::detail::void_ptr_to_reference(result(), (T(*)())0);
  248. }
  249. // arg_rvalue_from_python
  250. //
  251. template <class T>
  252. inline arg_rvalue_from_python<T>::arg_rvalue_from_python(PyObject* obj)
  253. : m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters))
  254. , m_source(obj)
  255. {
  256. }
  257. template <class T>
  258. inline bool arg_rvalue_from_python<T>::convertible() const
  259. {
  260. return m_data.stage1.convertible != 0;
  261. }
  262. template <class T>
  263. inline typename arg_rvalue_from_python<T>::result_type
  264. arg_rvalue_from_python<T>::operator()()
  265. {
  266. if (m_data.stage1.construct != 0)
  267. m_data.stage1.construct(m_source, &m_data.stage1);
  268. return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0);
  269. }
  270. // back_reference_arg_from_python
  271. //
  272. template <class T>
  273. back_reference_arg_from_python<T>::back_reference_arg_from_python(PyObject* x)
  274. : base(x), m_source(x)
  275. {
  276. }
  277. template <class T>
  278. inline T
  279. back_reference_arg_from_python<T>::operator()()
  280. {
  281. return T(m_source, base::operator()());
  282. }
  283. }}} // namespace boost::python::converter
  284. #endif // ARG_FROM_PYTHON_DWA2002127_HPP