source: NonGTP/Boost/boost/python/handle.hpp @ 857

Revision 857, 5.2 KB checked in by igarcia, 18 years ago (diff)
Line 
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
18namespace boost { namespace python {
19
20template <class T> struct null_ok;
21
22template <class T>
23inline null_ok<T>* allow_null(T* p)
24{
25    return (null_ok<T>*)p;
26}
27
28namespace 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
61template <class T>
62class 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
143template<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
149namespace python {
150#else
151
152// We don't want get_pointer above to hide the others
153using boost::get_pointer;
154
155#endif
156
157typedef handle<PyTypeObject> type_handle;
158
159//
160// Compile-time introspection
161//
162# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
163template<typename T>
164class is_handle
165{
166 public:
167    BOOST_STATIC_CONSTANT(bool, value = false);
168};
169
170template<typename T>
171class is_handle<handle<T> >
172{
173 public:
174    BOOST_STATIC_CONSTANT(bool, value = true);
175};
176# else
177namespace 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
188template<typename T>
189class 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//
202template <class T>
203inline handle<T>::handle()
204    : m_p(0)
205{
206}
207
208template <class T>
209inline handle<T>::~handle()
210{
211    python::xdecref(m_p);
212}
213
214template <class T>
215inline T* handle<T>::operator->() const
216{
217    return m_p;
218}
219
220template <class T>
221inline T& handle<T>::operator*() const
222{
223    return *m_p;
224}
225
226template <class T>
227inline T* handle<T>::get() const
228{
229    return m_p;
230}
231   
232template <class T>
233inline bool handle<T>::operator!() const
234{
235    return m_p == 0;
236}
237
238template <class T>
239inline T* handle<T>::release()
240{
241    T* result = m_p;
242    m_p = 0;
243    return result;
244}
245
246template <class T>
247inline 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.
255template <class T>
256inline 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
Note: See TracBrowser for help on using the repository browser.