[857] | 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
|
---|