• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright David Abrahams 2002.
2 // Copyright Stefan Seefeld 2016.
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef boost_python_to_python_value_hpp_
8 #define boost_python_to_python_value_hpp_
9 
10 #include <boost/python/detail/prefix.hpp>
11 
12 #include <boost/python/refcount.hpp>
13 #include <boost/python/tag.hpp>
14 #include <boost/python/handle.hpp>
15 
16 #include <boost/python/converter/registry.hpp>
17 #include <boost/python/converter/registered.hpp>
18 #include <boost/python/converter/builtin_converters.hpp>
19 #include <boost/python/converter/object_manager.hpp>
20 #include <boost/python/converter/shared_ptr_to_python.hpp>
21 
22 #include <boost/python/detail/type_traits.hpp>
23 #include <boost/python/detail/value_is_shared_ptr.hpp>
24 #include <boost/python/detail/value_arg.hpp>
25 
26 #include <boost/mpl/if.hpp>
27 #include <boost/mpl/or.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>
getboost::python::detail::object_manager_get_pytype39    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>
getboost::python::detail::object_manager_get_pytype49    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;
get_pytypeboost::python::detail::object_manager_to_python_value66       PyTypeObject const* get_pytype() const {
67           return get_pytype_aux((is_t_handle*)0);
68       }
69 
get_pytype_auxboost::python::detail::object_manager_to_python_value70       inline static PyTypeObject const* get_pytype_aux(mpl::true_*) {return converter::object_manager_traits<T>::get_pytype();}
71 
get_pytype_auxboost::python::detail::object_manager_to_python_value72       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
get_pytypeboost::python::detail::registry_to_python_value93       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
get_pytypeboost::python::detail::shared_ptr_to_python_value109       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>
get_pytypeboost::python::detail::shared_ptr_to_python_value118     PyTypeObject const* get_pytype(boost::type<shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();}
119     template <class U>
get_pytypeboost::python::detail::shared_ptr_to_python_value120     PyTypeObject const* get_pytype(boost::type<const shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();}
121 # if !defined(BOOST_NO_CXX11_SMART_PTR)
122     template <class U>
get_pytypeboost::python::detail::shared_ptr_to_python_value123     PyTypeObject const* get_pytype(boost::type<std::shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();}
124     template <class U>
get_pytypeboost::python::detail::shared_ptr_to_python_value125     PyTypeObject const* get_pytype(boost::type<const std::shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();}
126 # endif
127 #endif
128   };
129 }
130 
131 template <class T>
132 struct to_python_value
133     : mpl::if_<
134           detail::value_is_shared_ptr<T>
135         , detail::shared_ptr_to_python_value<T>
136         , typename mpl::if_<
137               mpl::or_<
138                   converter::is_object_manager<T>
139                 , converter::is_reference_to_object_manager<T>
140               >
141             , detail::object_manager_to_python_value<T>
142             , detail::registry_to_python_value<T>
143           >::type
144       >::type
145 {
146 };
147 
148 //
149 // implementation
150 //
151 namespace detail
152 {
153   template <class T>
operator ()(argument_type x) const154   inline PyObject* registry_to_python_value<T>::operator()(argument_type x) const
155   {
156       return converter::registered<argument_type>::converters.to_python(&x);
157   }
158 
159   template <class T>
operator ()(argument_type x) const160   inline PyObject* object_manager_to_python_value<T>::operator()(argument_type x) const
161   {
162       return python::upcast<PyObject>(
163           python::xincref(
164               get_managed_object(x, tag))
165           );
166   }
167 
168   template <class T>
operator ()(argument_type x) const169   inline PyObject* shared_ptr_to_python_value<T>::operator()(argument_type x) const
170   {
171       return converter::shared_ptr_to_python(x);
172   }
173 }
174 
175 }} // namespace boost::python
176 
177 #endif
178