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