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