[12] | 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 HANDLE_DWA200269_HPP |
---|
| 6 | # define HANDLE_DWA200269_HPP |
---|
| 7 | |
---|
| 8 | # include <boost/python/detail/prefix.hpp> |
---|
| 9 | |
---|
| 10 | # include <boost/python/cast.hpp> |
---|
| 11 | # include <boost/python/errors.hpp> |
---|
| 12 | # include <boost/python/borrowed.hpp> |
---|
| 13 | # include <boost/python/handle_fwd.hpp> |
---|
| 14 | # include <boost/python/refcount.hpp> |
---|
| 15 | # include <boost/python/tag.hpp> |
---|
| 16 | # include <boost/python/detail/raw_pyobject.hpp> |
---|
| 17 | |
---|
| 18 | namespace boost { namespace python { |
---|
| 19 | |
---|
| 20 | template <class T> struct null_ok; |
---|
| 21 | |
---|
| 22 | template <class T> |
---|
| 23 | inline null_ok<T>* allow_null(T* p) |
---|
| 24 | { |
---|
| 25 | return (null_ok<T>*)p; |
---|
| 26 | } |
---|
| 27 | |
---|
| 28 | namespace detail |
---|
| 29 | { |
---|
| 30 | template <class T> |
---|
| 31 | inline T* manage_ptr(detail::borrowed<null_ok<T> >* p, int) |
---|
| 32 | { |
---|
| 33 | return python::xincref((T*)p); |
---|
| 34 | } |
---|
| 35 | |
---|
| 36 | template <class T> |
---|
| 37 | inline T* manage_ptr(null_ok<detail::borrowed<T> >* p, int) |
---|
| 38 | { |
---|
| 39 | return python::xincref((T*)p); |
---|
| 40 | } |
---|
| 41 | |
---|
| 42 | template <class T> |
---|
| 43 | inline T* manage_ptr(detail::borrowed<T>* p, long) |
---|
| 44 | { |
---|
| 45 | return python::incref(expect_non_null((T*)p)); |
---|
| 46 | } |
---|
| 47 | |
---|
| 48 | template <class T> |
---|
| 49 | inline T* manage_ptr(null_ok<T>* p, long) |
---|
| 50 | { |
---|
| 51 | return (T*)p; |
---|
| 52 | } |
---|
| 53 | |
---|
| 54 | template <class T> |
---|
| 55 | inline T* manage_ptr(T* p, ...) |
---|
| 56 | { |
---|
| 57 | return expect_non_null(p); |
---|
| 58 | } |
---|
| 59 | } |
---|
| 60 | |
---|
| 61 | template <class T> |
---|
| 62 | class handle |
---|
| 63 | { |
---|
| 64 | typedef T* (handle::* bool_type )() const; |
---|
| 65 | |
---|
| 66 | public: // types |
---|
| 67 | typedef T element_type; |
---|
| 68 | |
---|
| 69 | public: // member functions |
---|
| 70 | handle(); |
---|
| 71 | ~handle(); |
---|
| 72 | |
---|
| 73 | template <class Y> |
---|
| 74 | explicit handle(Y* p) |
---|
| 75 | : m_p( |
---|
| 76 | python::upcast<T>( |
---|
| 77 | detail::manage_ptr(p, 0) |
---|
| 78 | ) |
---|
| 79 | ) |
---|
| 80 | { |
---|
| 81 | } |
---|
| 82 | |
---|
| 83 | handle& operator=(handle const& r) |
---|
| 84 | { |
---|
| 85 | python::xdecref(m_p); |
---|
| 86 | m_p = python::xincref(r.m_p); |
---|
| 87 | return *this; |
---|
| 88 | } |
---|
| 89 | |
---|
| 90 | #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) |
---|
| 91 | |
---|
| 92 | template<typename Y> |
---|
| 93 | handle& operator=(handle<Y> const & r) // never throws |
---|
| 94 | { |
---|
| 95 | python::xdecref(m_p); |
---|
| 96 | m_p = python::xincref(python::upcast<T>(r.get())); |
---|
| 97 | return *this; |
---|
| 98 | } |
---|
| 99 | |
---|
| 100 | #endif |
---|
| 101 | |
---|
| 102 | template <typename Y> |
---|
| 103 | handle(handle<Y> const& r) |
---|
| 104 | : m_p(python::xincref(python::upcast<T>(r.get()))) |
---|
| 105 | { |
---|
| 106 | } |
---|
| 107 | |
---|
| 108 | handle(handle const& r) |
---|
| 109 | : m_p(python::xincref(r.m_p)) |
---|
| 110 | { |
---|
| 111 | } |
---|
| 112 | |
---|
| 113 | T* operator-> () const; |
---|
| 114 | T& operator* () const; |
---|
| 115 | T* get() const; |
---|
| 116 | T* release(); |
---|
| 117 | void reset(); |
---|
| 118 | |
---|
| 119 | operator bool_type() const // never throws |
---|
| 120 | { |
---|
| 121 | return m_p ? &handle<T>::get : 0; |
---|
| 122 | } |
---|
| 123 | bool operator! () const; // never throws |
---|
| 124 | |
---|
| 125 | public: // implementation details -- do not touch |
---|
| 126 | // Defining this in the class body suppresses a VC7 link failure |
---|
| 127 | inline handle(detail::borrowed_reference x) |
---|
| 128 | : m_p( |
---|
| 129 | python::incref( |
---|
| 130 | downcast<T>((PyObject*)x) |
---|
| 131 | )) |
---|
| 132 | { |
---|
| 133 | } |
---|
| 134 | |
---|
| 135 | private: // data members |
---|
| 136 | T* m_p; |
---|
| 137 | }; |
---|
| 138 | |
---|
| 139 | #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP |
---|
| 140 | } // namespace python |
---|
| 141 | #endif |
---|
| 142 | |
---|
| 143 | template<class T> inline T * get_pointer(python::handle<T> const & p) |
---|
| 144 | { |
---|
| 145 | return p.get(); |
---|
| 146 | } |
---|
| 147 | |
---|
| 148 | #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP |
---|
| 149 | namespace python { |
---|
| 150 | #else |
---|
| 151 | |
---|
| 152 | // We don't want get_pointer above to hide the others |
---|
| 153 | using boost::get_pointer; |
---|
| 154 | |
---|
| 155 | #endif |
---|
| 156 | |
---|
| 157 | typedef handle<PyTypeObject> type_handle; |
---|
| 158 | |
---|
| 159 | // |
---|
| 160 | // Compile-time introspection |
---|
| 161 | // |
---|
| 162 | # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
---|
| 163 | template<typename T> |
---|
| 164 | class is_handle |
---|
| 165 | { |
---|
| 166 | public: |
---|
| 167 | BOOST_STATIC_CONSTANT(bool, value = false); |
---|
| 168 | }; |
---|
| 169 | |
---|
| 170 | template<typename T> |
---|
| 171 | class is_handle<handle<T> > |
---|
| 172 | { |
---|
| 173 | public: |
---|
| 174 | BOOST_STATIC_CONSTANT(bool, value = true); |
---|
| 175 | }; |
---|
| 176 | # else |
---|
| 177 | namespace detail |
---|
| 178 | { |
---|
| 179 | typedef char (&yes_handle_t)[1]; |
---|
| 180 | typedef char (&no_handle_t)[2]; |
---|
| 181 | |
---|
| 182 | no_handle_t is_handle_test(...); |
---|
| 183 | |
---|
| 184 | template<typename T> |
---|
| 185 | yes_handle_t is_handle_test(boost::type< handle<T> >); |
---|
| 186 | } |
---|
| 187 | |
---|
| 188 | template<typename T> |
---|
| 189 | class is_handle |
---|
| 190 | { |
---|
| 191 | public: |
---|
| 192 | BOOST_STATIC_CONSTANT( |
---|
| 193 | bool, value = ( |
---|
| 194 | sizeof(detail::is_handle_test(boost::type<T>())) |
---|
| 195 | == sizeof(detail::yes_handle_t))); |
---|
| 196 | }; |
---|
| 197 | # endif |
---|
| 198 | |
---|
| 199 | // |
---|
| 200 | // implementations |
---|
| 201 | // |
---|
| 202 | template <class T> |
---|
| 203 | inline handle<T>::handle() |
---|
| 204 | : m_p(0) |
---|
| 205 | { |
---|
| 206 | } |
---|
| 207 | |
---|
| 208 | template <class T> |
---|
| 209 | inline handle<T>::~handle() |
---|
| 210 | { |
---|
| 211 | python::xdecref(m_p); |
---|
| 212 | } |
---|
| 213 | |
---|
| 214 | template <class T> |
---|
| 215 | inline T* handle<T>::operator->() const |
---|
| 216 | { |
---|
| 217 | return m_p; |
---|
| 218 | } |
---|
| 219 | |
---|
| 220 | template <class T> |
---|
| 221 | inline T& handle<T>::operator*() const |
---|
| 222 | { |
---|
| 223 | return *m_p; |
---|
| 224 | } |
---|
| 225 | |
---|
| 226 | template <class T> |
---|
| 227 | inline T* handle<T>::get() const |
---|
| 228 | { |
---|
| 229 | return m_p; |
---|
| 230 | } |
---|
| 231 | |
---|
| 232 | template <class T> |
---|
| 233 | inline bool handle<T>::operator!() const |
---|
| 234 | { |
---|
| 235 | return m_p == 0; |
---|
| 236 | } |
---|
| 237 | |
---|
| 238 | template <class T> |
---|
| 239 | inline T* handle<T>::release() |
---|
| 240 | { |
---|
| 241 | T* result = m_p; |
---|
| 242 | m_p = 0; |
---|
| 243 | return result; |
---|
| 244 | } |
---|
| 245 | |
---|
| 246 | template <class T> |
---|
| 247 | inline void handle<T>::reset() |
---|
| 248 | { |
---|
| 249 | python::xdecref(m_p); |
---|
| 250 | m_p = 0; |
---|
| 251 | } |
---|
| 252 | |
---|
| 253 | // Because get_managed_object must return a non-null PyObject*, we |
---|
| 254 | // return Py_None if the handle is null. |
---|
| 255 | template <class T> |
---|
| 256 | inline PyObject* get_managed_object(handle<T> const& h, tag_t) |
---|
| 257 | { |
---|
| 258 | return h.get() ? python::upcast<PyObject>(h.get()) : Py_None; |
---|
| 259 | } |
---|
| 260 | |
---|
| 261 | }} // namespace boost::python |
---|
| 262 | |
---|
| 263 | |
---|
| 264 | #endif // HANDLE_DWA200269_HPP |
---|