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