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 OBJECT_MANAGER_DWA2002614_HPP 6 # define OBJECT_MANAGER_DWA2002614_HPP 7 8 # include <boost/python/handle.hpp> 9 # include <boost/python/cast.hpp> 10 # include <boost/python/converter/pyobject_traits.hpp> 11 # include <boost/python/detail/type_traits.hpp> 12 # include <boost/mpl/if.hpp> 13 # include <boost/python/detail/indirect_traits.hpp> 14 # include <boost/mpl/bool.hpp> 15 16 // Facilities for dealing with types which always manage Python 17 // objects. Some examples are object, list, str, et. al. Different 18 // to_python/from_python conversion rules apply here because in 19 // contrast to other types which are typically embedded inside a 20 // Python object, these are wrapped around a Python object. For most 21 // object managers T, a C++ non-const T reference argument does not 22 // imply the existence of a T lvalue embedded in the corresponding 23 // Python argument, since mutating member functions on T actually only 24 // modify the held Python object. 25 // 26 // handle<T> is an object manager, though strictly speaking it should 27 // not be. In other words, even though mutating member functions of 28 // hanlde<T> actually modify the handle<T> and not the T object, 29 // handle<T>& arguments of wrapped functions will bind to "rvalues" 30 // wrapping the actual Python argument, just as with other object 31 // manager classes. Making an exception for handle<T> is simply not 32 // worth the trouble. 33 // 34 // borrowed<T> cv* is an object manager so that we can use the general 35 // to_python mechanisms to convert raw Python object pointers to 36 // python, without the usual semantic problems of using raw pointers. 37 38 39 // Object Manager Concept requirements: 40 // 41 // T is an Object Manager 42 // p is a PyObject* 43 // x is a T 44 // 45 // * object_manager_traits<T>::is_specialized == true 46 // 47 // * T(detail::borrowed_reference(p)) 48 // Manages p without checking its type 49 // 50 // * get_managed_object(x, boost::python::tag) 51 // Convertible to PyObject* 52 // 53 // Additional requirements if T can be converted from_python: 54 // 55 // * T(object_manager_traits<T>::adopt(p)) 56 // steals a reference to p, or throws a TypeError exception if 57 // p doesn't have an appropriate type. May assume p is non-null 58 // 59 // * X::check(p) 60 // convertible to bool. True iff T(X::construct(p)) will not 61 // throw. 62 63 // Forward declarations 64 // 65 namespace boost { namespace python 66 { 67 namespace api 68 { 69 class object; 70 } 71 }} 72 73 namespace boost { namespace python { namespace converter { 74 75 76 // Specializations for handle<T> 77 template <class T> 78 struct handle_object_manager_traits 79 : pyobject_traits<typename T::element_type> 80 { 81 private: 82 typedef pyobject_traits<typename T::element_type> base; 83 84 public: 85 BOOST_STATIC_CONSTANT(bool, is_specialized = true); 86 87 // Initialize with a null_ok pointer for efficiency, bypassing the 88 // null check since the source is always non-null. adoptboost::python::converter::handle_object_manager_traits89 static null_ok<typename T::element_type>* adopt(PyObject* p) 90 { 91 return python::allow_null(base::checked_downcast(p)); 92 } 93 }; 94 95 template <class T> 96 struct default_object_manager_traits 97 { 98 BOOST_STATIC_CONSTANT( 99 bool, is_specialized = python::detail::is_borrowed_ptr<T>::value 100 ); 101 }; 102 103 template <class T> 104 struct object_manager_traits 105 : mpl::if_c< 106 is_handle<T>::value 107 , handle_object_manager_traits<T> 108 , default_object_manager_traits<T> 109 >::type 110 { 111 }; 112 113 // 114 // Traits for detecting whether a type is an object manager or a 115 // (cv-qualified) reference to an object manager. 116 // 117 118 template <class T> 119 struct is_object_manager 120 : mpl::bool_<object_manager_traits<T>::is_specialized> 121 { 122 }; 123 124 template <class T> 125 struct is_reference_to_object_manager 126 : mpl::false_ 127 { 128 }; 129 130 template <class T> 131 struct is_reference_to_object_manager<T&> 132 : is_object_manager<T> 133 { 134 }; 135 136 template <class T> 137 struct is_reference_to_object_manager<T const&> 138 : is_object_manager<T> 139 { 140 }; 141 142 template <class T> 143 struct is_reference_to_object_manager<T volatile&> 144 : is_object_manager<T> 145 { 146 }; 147 148 template <class T> 149 struct is_reference_to_object_manager<T const volatile&> 150 : is_object_manager<T> 151 { 152 }; 153 154 }}} // namespace boost::python::converter 155 156 #endif // OBJECT_MANAGER_DWA2002614_HPP 157