arg_to_python.hpp 7.2 KB

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