arg_to_python.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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_TO_PYTHON_DWA200265_HPP
  6. # define ARG_TO_PYTHON_DWA200265_HPP
  7. # include <boost/python/ptr.hpp>
  8. # include <boost/python/tag.hpp>
  9. # include <boost/python/to_python_indirect.hpp>
  10. # include <boost/python/converter/registered.hpp>
  11. # include <boost/python/converter/registered_pointee.hpp>
  12. # include <boost/python/converter/arg_to_python_base.hpp>
  13. # include <boost/python/converter/shared_ptr_to_python.hpp>
  14. // Bring in specializations
  15. # include <boost/python/converter/builtin_converters.hpp>
  16. # include <boost/python/object/function_handle.hpp>
  17. # include <boost/python/base_type_traits.hpp>
  18. # include <boost/python/detail/indirect_traits.hpp>
  19. # include <boost/python/detail/convertible.hpp>
  20. # include <boost/python/detail/string_literal.hpp>
  21. # include <boost/python/detail/value_is_shared_ptr.hpp>
  22. # include <boost/type_traits/cv_traits.hpp>
  23. # include <boost/type_traits/composite_traits.hpp>
  24. # include <boost/type_traits/function_traits.hpp>
  25. # include <boost/mpl/or.hpp>
  26. namespace boost { namespace python { namespace converter {
  27. template <class T> struct is_object_manager;
  28. namespace detail
  29. {
  30. template <class T>
  31. struct function_arg_to_python : handle<>
  32. {
  33. function_arg_to_python(T const& x);
  34. };
  35. template <class T>
  36. struct reference_arg_to_python : handle<>
  37. {
  38. reference_arg_to_python(T& x);
  39. private:
  40. static PyObject* get_object(T& x);
  41. };
  42. template <class T>
  43. struct shared_ptr_arg_to_python : handle<>
  44. {
  45. shared_ptr_arg_to_python(T const& x);
  46. private:
  47. static PyObject* get_object(T& x);
  48. };
  49. template <class T>
  50. struct value_arg_to_python : arg_to_python_base
  51. {
  52. // Throw an exception if the conversion can't succeed
  53. value_arg_to_python(T const&);
  54. };
  55. template <class Ptr>
  56. struct pointer_deep_arg_to_python : arg_to_python_base
  57. {
  58. // Throw an exception if the conversion can't succeed
  59. pointer_deep_arg_to_python(Ptr);
  60. };
  61. template <class Ptr>
  62. struct pointer_shallow_arg_to_python : handle<>
  63. {
  64. // Throw an exception if the conversion can't succeed
  65. pointer_shallow_arg_to_python(Ptr);
  66. private:
  67. static PyObject* get_object(Ptr p);
  68. };
  69. // Convert types that manage a Python object to_python
  70. template <class T>
  71. struct object_manager_arg_to_python
  72. {
  73. object_manager_arg_to_python(T const& x) : m_src(x) {}
  74. PyObject* get() const
  75. {
  76. return python::upcast<PyObject>(get_managed_object(m_src, tag));
  77. }
  78. private:
  79. T const& m_src;
  80. };
  81. template <class T>
  82. struct select_arg_to_python
  83. {
  84. typedef typename unwrap_reference<T>::type unwrapped_referent;
  85. typedef typename unwrap_pointer<T>::type unwrapped_ptr;
  86. typedef typename mpl::if_<
  87. // Special handling for char const[N]; interpret them as char
  88. // const* for the sake of conversion
  89. python::detail::is_string_literal<T const>
  90. , arg_to_python<char const*>
  91. , typename mpl::if_<
  92. python::detail::value_is_shared_ptr<T>
  93. , shared_ptr_arg_to_python<T>
  94. , typename mpl::if_<
  95. mpl::or_<
  96. is_function<T>
  97. , indirect_traits::is_pointer_to_function<T>
  98. , is_member_function_pointer<T>
  99. >
  100. , function_arg_to_python<T>
  101. , typename mpl::if_<
  102. is_object_manager<T>
  103. , object_manager_arg_to_python<T>
  104. , typename mpl::if_<
  105. is_pointer<T>
  106. , pointer_deep_arg_to_python<T>
  107. , typename mpl::if_<
  108. is_pointer_wrapper<T>
  109. , pointer_shallow_arg_to_python<unwrapped_ptr>
  110. , typename mpl::if_<
  111. is_reference_wrapper<T>
  112. , reference_arg_to_python<unwrapped_referent>
  113. , value_arg_to_python<T>
  114. >::type
  115. >::type
  116. >::type
  117. >::type
  118. >::type
  119. >::type
  120. >::type
  121. type;
  122. };
  123. }
  124. template <class T>
  125. struct arg_to_python
  126. : detail::select_arg_to_python<T>::type
  127. {
  128. typedef typename detail::select_arg_to_python<T>::type base;
  129. public: // member functions
  130. // Throw an exception if the conversion can't succeed
  131. arg_to_python(T const& x);
  132. };
  133. //
  134. // implementations
  135. //
  136. namespace detail
  137. {
  138. // reject_raw_object_ptr -- cause a compile-time error if the user
  139. // should pass a raw Python object pointer
  140. using python::detail::yes_convertible;
  141. using python::detail::no_convertible;
  142. using python::detail::unspecialized;
  143. template <class T> struct cannot_convert_raw_PyObject;
  144. template <class T, class Convertibility>
  145. struct reject_raw_object_helper
  146. {
  147. static void error(Convertibility)
  148. {
  149. cannot_convert_raw_PyObject<T*>::to_python_use_handle_instead();
  150. }
  151. static void error(...) {}
  152. };
  153. template <class T>
  154. inline void reject_raw_object_ptr(T*)
  155. {
  156. reject_raw_object_helper<T,yes_convertible>::error(
  157. python::detail::convertible<PyObject const volatile*>::check((T*)0));
  158. typedef typename remove_cv<T>::type value_type;
  159. reject_raw_object_helper<T,no_convertible>::error(
  160. python::detail::convertible<unspecialized*>::check(
  161. (base_type_traits<value_type>*)0
  162. ));
  163. }
  164. // ---------
  165. template <class T>
  166. inline function_arg_to_python<T>::function_arg_to_python(T const& x)
  167. : handle<>(python::objects::make_function_handle(x))
  168. {
  169. }
  170. template <class T>
  171. inline value_arg_to_python<T>::value_arg_to_python(T const& x)
  172. : arg_to_python_base(&x, registered<T>::converters)
  173. {
  174. }
  175. template <class Ptr>
  176. inline pointer_deep_arg_to_python<Ptr>::pointer_deep_arg_to_python(Ptr x)
  177. : arg_to_python_base(x, registered_pointee<Ptr>::converters)
  178. {
  179. detail::reject_raw_object_ptr((Ptr)0);
  180. }
  181. template <class T>
  182. inline PyObject* reference_arg_to_python<T>::get_object(T& x)
  183. {
  184. to_python_indirect<T&,python::detail::make_reference_holder> convert;
  185. return convert(x);
  186. }
  187. template <class T>
  188. inline reference_arg_to_python<T>::reference_arg_to_python(T& x)
  189. : handle<>(reference_arg_to_python<T>::get_object(x))
  190. {
  191. }
  192. template <class T>
  193. inline shared_ptr_arg_to_python<T>::shared_ptr_arg_to_python(T const& x)
  194. : handle<>(shared_ptr_to_python(x))
  195. {
  196. }
  197. template <class Ptr>
  198. inline pointer_shallow_arg_to_python<Ptr>::pointer_shallow_arg_to_python(Ptr x)
  199. : handle<>(pointer_shallow_arg_to_python<Ptr>::get_object(x))
  200. {
  201. detail::reject_raw_object_ptr((Ptr)0);
  202. }
  203. template <class Ptr>
  204. inline PyObject* pointer_shallow_arg_to_python<Ptr>::get_object(Ptr x)
  205. {
  206. to_python_indirect<Ptr,python::detail::make_reference_holder> convert;
  207. return convert(x);
  208. }
  209. }
  210. template <class T>
  211. inline arg_to_python<T>::arg_to_python(T const& x)
  212. : base(x)
  213. {}
  214. }}} // namespace boost::python::converter
  215. #endif // ARG_TO_PYTHON_DWA200265_HPP