arg_from_python.hpp 9.0 KB

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