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 TO_PYTHON_VALUE_DWA200221_HPP |
6 | # define TO_PYTHON_VALUE_DWA200221_HPP |
7 | |
8 | # include <boost/python/detail/prefix.hpp> |
9 | |
10 | # include <boost/python/refcount.hpp> |
11 | # include <boost/python/tag.hpp> |
12 | # include <boost/python/handle.hpp> |
13 | |
14 | # include <boost/python/converter/registry.hpp> |
15 | # include <boost/python/converter/registered.hpp> |
16 | # include <boost/python/converter/builtin_converters.hpp> |
17 | # include <boost/python/converter/object_manager.hpp> |
18 | # include <boost/python/converter/shared_ptr_to_python.hpp> |
19 | |
20 | # include <boost/python/detail/value_is_shared_ptr.hpp> |
21 | # include <boost/python/detail/value_arg.hpp> |
22 | |
23 | # include <boost/type_traits/transform_traits.hpp> |
24 | |
25 | # include <boost/mpl/if.hpp> |
26 | # include <boost/mpl/or.hpp> |
27 | # include <boost/type_traits/is_const.hpp> |
28 | |
29 | namespace boost { namespace python { |
30 | |
31 | namespace detail |
32 | { |
33 | #ifndef BOOST_PYTHON_NO_PY_SIGNATURES |
34 | |
35 | template <bool is_const_ref> |
36 | struct object_manager_get_pytype |
37 | { |
38 | template <class U> |
39 | static PyTypeObject const* get( U& (*)() =0) |
40 | { |
41 | return converter::object_manager_traits<U>::get_pytype(); |
42 | } |
43 | }; |
44 | |
45 | template <> |
46 | struct object_manager_get_pytype<true> |
47 | { |
48 | template <class U> |
49 | static PyTypeObject const* get( U const& (*)() =0) |
50 | { |
51 | return converter::object_manager_traits<U>::get_pytype(); |
52 | } |
53 | }; |
54 | |
55 | #endif |
56 | |
57 | template <class T> |
58 | struct object_manager_to_python_value |
59 | { |
60 | typedef typename value_arg<T>::type argument_type; |
61 | |
62 | PyObject* operator()(argument_type) const; |
63 | #ifndef BOOST_PYTHON_NO_PY_SIGNATURES |
64 | typedef boost::mpl::bool_<is_handle<T>::value> is_t_handle; |
65 | typedef boost::detail::indirect_traits::is_reference_to_const<T> is_t_const; |
66 | PyTypeObject const* get_pytype() const { |
67 | return get_pytype_aux((is_t_handle*)0); |
68 | } |
69 | |
70 | inline static PyTypeObject const* get_pytype_aux(mpl::true_*) {return converter::object_manager_traits<T>::get_pytype();} |
71 | |
72 | inline static PyTypeObject const* get_pytype_aux(mpl::false_* ) |
73 | { |
74 | return object_manager_get_pytype<is_t_const::value>::get((T(*)())0); |
75 | } |
76 | |
77 | #endif |
78 | |
79 | // This information helps make_getter() decide whether to try to |
80 | // return an internal reference or not. I don't like it much, |
81 | // but it will have to serve for now. |
82 | BOOST_STATIC_CONSTANT(bool, uses_registry = false); |
83 | }; |
84 | |
85 | |
86 | template <class T> |
87 | struct registry_to_python_value |
88 | { |
89 | typedef typename value_arg<T>::type argument_type; |
90 | |
91 | PyObject* operator()(argument_type) const; |
92 | #ifndef BOOST_PYTHON_NO_PY_SIGNATURES |
93 | PyTypeObject const* get_pytype() const {return converter::registered<T>::converters.to_python_target_type();} |
94 | #endif |
95 | |
96 | // This information helps make_getter() decide whether to try to |
97 | // return an internal reference or not. I don't like it much, |
98 | // but it will have to serve for now. |
99 | BOOST_STATIC_CONSTANT(bool, uses_registry = true); |
100 | }; |
101 | |
102 | template <class T> |
103 | struct shared_ptr_to_python_value |
104 | { |
105 | typedef typename value_arg<T>::type argument_type; |
106 | |
107 | PyObject* operator()(argument_type) const; |
108 | #ifndef BOOST_PYTHON_NO_PY_SIGNATURES |
109 | PyTypeObject const* get_pytype() const {return get_pytype((boost::type<argument_type>*)0);} |
110 | #endif |
111 | // This information helps make_getter() decide whether to try to |
112 | // return an internal reference or not. I don't like it much, |
113 | // but it will have to serve for now. |
114 | BOOST_STATIC_CONSTANT(bool, uses_registry = false); |
115 | private: |
116 | #ifndef BOOST_PYTHON_NO_PY_SIGNATURES |
117 | template <class U> |
118 | PyTypeObject const* get_pytype(boost::type<shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();} |
119 | template <class U> |
120 | PyTypeObject const* get_pytype(boost::type<const shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();} |
121 | #endif |
122 | }; |
123 | } |
124 | |
125 | template <class T> |
126 | struct to_python_value |
127 | : mpl::if_< |
128 | detail::value_is_shared_ptr<T> |
129 | , detail::shared_ptr_to_python_value<T> |
130 | , typename mpl::if_< |
131 | mpl::or_< |
132 | converter::is_object_manager<T> |
133 | , converter::is_reference_to_object_manager<T> |
134 | > |
135 | , detail::object_manager_to_python_value<T> |
136 | , detail::registry_to_python_value<T> |
137 | >::type |
138 | >::type |
139 | { |
140 | }; |
141 | |
142 | // |
143 | // implementation |
144 | // |
145 | namespace detail |
146 | { |
147 | template <class T> |
148 | inline PyObject* registry_to_python_value<T>::operator()(argument_type x) const |
149 | { |
150 | return converter::registered<argument_type>::converters.to_python(&x); |
151 | } |
152 | |
153 | template <class T> |
154 | inline PyObject* object_manager_to_python_value<T>::operator()(argument_type x) const |
155 | { |
156 | return python::upcast<PyObject>( |
157 | python::xincref( |
158 | get_managed_object(x, tag)) |
159 | ); |
160 | } |
161 | |
162 | template <class T> |
163 | inline PyObject* shared_ptr_to_python_value<T>::operator()(argument_type x) const |
164 | { |
165 | return converter::shared_ptr_to_python(x); |
166 | } |
167 | } |
168 | |
169 | }} // namespace boost::python |
170 | |
171 | #endif // TO_PYTHON_VALUE_DWA200221_HPP |
172 | |