• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
allow_null(T * p)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>
manage_ptr(detail::borrowed<null_ok<T>> * p,int)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>
manage_ptr(null_ok<detail::borrowed<T>> * p,int)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>
manage_ptr(detail::borrowed<T> * p,long)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>
manage_ptr(null_ok<T> * p,long)49   inline T* manage_ptr(null_ok<T>* p, long)
50   {
51       return (T*)p;
52   }
53 
54   template <class T>
manage_ptr(T * p,...)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>
handle(Y * p)74     explicit handle(Y* p)
75         : m_p(
76             python::upcast<T>(
77                 detail::manage_ptr(p, 0)
78                 )
79             )
80     {
81     }
82 
operator =(handle const & r)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>
operator =(handle<Y> const & r)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>
handle(handle<Y> const & r)99     handle(handle<Y> const& r)
100         : m_p(python::xincref(python::upcast<T>(r.get())))
101     {
102     }
103 
handle(handle const & r)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 
operator bool_type() const115     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
handle(detail::borrowed_reference x)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 
get_pointer(python::handle<T> const & p)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>
handle()176 inline handle<T>::handle()
177     : m_p(0)
178 {
179 }
180 
181 template <class T>
~handle()182 inline handle<T>::~handle()
183 {
184     python::xdecref(m_p);
185 }
186 
187 template <class T>
operator ->() const188 inline T* handle<T>::operator->() const
189 {
190     return m_p;
191 }
192 
193 template <class T>
operator *() const194 inline T& handle<T>::operator*() const
195 {
196     return *m_p;
197 }
198 
199 template <class T>
get() const200 inline T* handle<T>::get() const
201 {
202     return m_p;
203 }
204 
205 template <class T>
operator !() const206 inline bool handle<T>::operator!() const
207 {
208     return m_p == 0;
209 }
210 
211 template <class T>
release()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>
reset()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>
get_managed_object(handle<T> const & h,tag_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