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 | template<typename Y> |
91 | handle& operator=(handle<Y> const & r) // never throws |
92 | { |
93 | python::xdecref(m_p); |
94 | m_p = python::xincref(python::upcast<T>(r.get())); |
95 | return *this; |
96 | } |
97 | |
98 | template <typename Y> |
99 | handle(handle<Y> const& r) |
100 | : m_p(python::xincref(python::upcast<T>(r.get()))) |
101 | { |
102 | } |
103 | |
104 | handle(handle const& r) |
105 | : m_p(python::xincref(r.m_p)) |
106 | { |
107 | } |
108 | |
109 | T* operator-> () const; |
110 | T& operator* () const; |
111 | T* get() const; |
112 | T* release(); |
113 | void reset(); |
114 | |
115 | operator bool_type() const // never throws |
116 | { |
117 | return m_p ? &handle<T>::get : 0; |
118 | } |
119 | bool operator! () const; // never throws |
120 | |
121 | public: // implementation details -- do not touch |
122 | // Defining this in the class body suppresses a VC7 link failure |
123 | inline handle(detail::borrowed_reference x) |
124 | : m_p( |
125 | python::incref( |
126 | downcast<T>((PyObject*)x) |
127 | )) |
128 | { |
129 | } |
130 | |
131 | private: // data members |
132 | T* m_p; |
133 | }; |
134 | |
135 | #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP |
136 | } // namespace python |
137 | #endif |
138 | |
139 | template<class T> inline T * get_pointer(python::handle<T> const & p) |
140 | { |
141 | return p.get(); |
142 | } |
143 | |
144 | #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP |
145 | namespace python { |
146 | #else |
147 | |
148 | // We don't want get_pointer above to hide the others |
149 | using boost::get_pointer; |
150 | |
151 | #endif |
152 | |
153 | typedef handle<PyTypeObject> type_handle; |
154 | |
155 | // |
156 | // Compile-time introspection |
157 | // |
158 | template<typename T> |
159 | class is_handle |
160 | { |
161 | public: |
162 | BOOST_STATIC_CONSTANT(bool, value = false); |
163 | }; |
164 | |
165 | template<typename T> |
166 | class is_handle<handle<T> > |
167 | { |
168 | public: |
169 | BOOST_STATIC_CONSTANT(bool, value = true); |
170 | }; |
171 | |
172 | // |
173 | // implementations |
174 | // |
175 | template <class T> |
176 | inline handle<T>::handle() |
177 | : m_p(0) |
178 | { |
179 | } |
180 | |
181 | template <class T> |
182 | inline handle<T>::~handle() |
183 | { |
184 | python::xdecref(m_p); |
185 | } |
186 | |
187 | template <class T> |
188 | inline T* handle<T>::operator->() const |
189 | { |
190 | return m_p; |
191 | } |
192 | |
193 | template <class T> |
194 | inline T& handle<T>::operator*() const |
195 | { |
196 | return *m_p; |
197 | } |
198 | |
199 | template <class T> |
200 | inline T* handle<T>::get() const |
201 | { |
202 | return m_p; |
203 | } |
204 | |
205 | template <class T> |
206 | inline bool handle<T>::operator!() const |
207 | { |
208 | return m_p == 0; |
209 | } |
210 | |
211 | template <class T> |
212 | inline T* handle<T>::release() |
213 | { |
214 | T* result = m_p; |
215 | m_p = 0; |
216 | return result; |
217 | } |
218 | |
219 | template <class T> |
220 | inline void handle<T>::reset() |
221 | { |
222 | python::xdecref(m_p); |
223 | m_p = 0; |
224 | } |
225 | |
226 | // Because get_managed_object must return a non-null PyObject*, we |
227 | // return Py_None if the handle is null. |
228 | template <class T> |
229 | inline PyObject* get_managed_object(handle<T> const& h, tag_t) |
230 | { |
231 | return h.get() ? python::upcast<PyObject>(h.get()) : Py_None; |
232 | } |
233 | |
234 | }} // namespace boost::python |
235 | |
236 | |
237 | #endif // HANDLE_DWA200269_HPP |
238 | |