| // Copyright David Abrahams 2002. |
| // Distributed under the Boost Software License, Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| #ifndef HANDLE_DWA200269_HPP |
| # define HANDLE_DWA200269_HPP |
| |
| # include <boost/python/detail/prefix.hpp> |
| |
| # include <boost/python/cast.hpp> |
| # include <boost/python/errors.hpp> |
| # include <boost/python/borrowed.hpp> |
| # include <boost/python/handle_fwd.hpp> |
| # include <boost/python/refcount.hpp> |
| # include <boost/python/tag.hpp> |
| # include <boost/python/detail/raw_pyobject.hpp> |
| |
| namespace boost { namespace python { |
| |
| template <class T> struct null_ok; |
| |
| template <class T> |
| inline null_ok<T>* allow_null(T* p) |
| { |
| return (null_ok<T>*)p; |
| } |
| |
| namespace detail |
| { |
| template <class T> |
| inline T* manage_ptr(detail::borrowed<null_ok<T> >* p, int) |
| { |
| return python::xincref((T*)p); |
| } |
| |
| template <class T> |
| inline T* manage_ptr(null_ok<detail::borrowed<T> >* p, int) |
| { |
| return python::xincref((T*)p); |
| } |
| |
| template <class T> |
| inline T* manage_ptr(detail::borrowed<T>* p, long) |
| { |
| return python::incref(expect_non_null((T*)p)); |
| } |
| |
| template <class T> |
| inline T* manage_ptr(null_ok<T>* p, long) |
| { |
| return (T*)p; |
| } |
| |
| template <class T> |
| inline T* manage_ptr(T* p, ...) |
| { |
| return expect_non_null(p); |
| } |
| } |
| |
| template <class T> |
| class handle |
| { |
| typedef T* (handle::* bool_type )() const; |
| |
| public: // types |
| typedef T element_type; |
| |
| public: // member functions |
| handle(); |
| ~handle(); |
| |
| template <class Y> |
| explicit handle(Y* p) |
| : m_p( |
| python::upcast<T>( |
| detail::manage_ptr(p, 0) |
| ) |
| ) |
| { |
| } |
| |
| handle& operator=(handle const& r) |
| { |
| python::xdecref(m_p); |
| m_p = python::xincref(r.m_p); |
| return *this; |
| } |
| |
| #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) |
| |
| template<typename Y> |
| handle& operator=(handle<Y> const & r) // never throws |
| { |
| python::xdecref(m_p); |
| m_p = python::xincref(python::upcast<T>(r.get())); |
| return *this; |
| } |
| |
| #endif |
| |
| template <typename Y> |
| handle(handle<Y> const& r) |
| : m_p(python::xincref(python::upcast<T>(r.get()))) |
| { |
| } |
| |
| handle(handle const& r) |
| : m_p(python::xincref(r.m_p)) |
| { |
| } |
| |
| T* operator-> () const; |
| T& operator* () const; |
| T* get() const; |
| T* release(); |
| void reset(); |
| |
| operator bool_type() const // never throws |
| { |
| return m_p ? &handle<T>::get : 0; |
| } |
| bool operator! () const; // never throws |
| |
| public: // implementation details -- do not touch |
| // Defining this in the class body suppresses a VC7 link failure |
| inline handle(detail::borrowed_reference x) |
| : m_p( |
| python::incref( |
| downcast<T>((PyObject*)x) |
| )) |
| { |
| } |
| |
| private: // data members |
| T* m_p; |
| }; |
| |
| #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP |
| } // namespace python |
| #endif |
| |
| template<class T> inline T * get_pointer(python::handle<T> const & p) |
| { |
| return p.get(); |
| } |
| |
| #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP |
| namespace python { |
| #else |
| |
| // We don't want get_pointer above to hide the others |
| using boost::get_pointer; |
| |
| #endif |
| |
| typedef handle<PyTypeObject> type_handle; |
| |
| // |
| // Compile-time introspection |
| // |
| # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template<typename T> |
| class is_handle |
| { |
| public: |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| |
| template<typename T> |
| class is_handle<handle<T> > |
| { |
| public: |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| # else |
| namespace detail |
| { |
| typedef char (&yes_handle_t)[1]; |
| typedef char (&no_handle_t)[2]; |
| |
| no_handle_t is_handle_test(...); |
| |
| template<typename T> |
| yes_handle_t is_handle_test(boost::type< handle<T> >); |
| } |
| |
| template<typename T> |
| class is_handle |
| { |
| public: |
| BOOST_STATIC_CONSTANT( |
| bool, value = ( |
| sizeof(detail::is_handle_test(boost::type<T>())) |
| == sizeof(detail::yes_handle_t))); |
| }; |
| # endif |
| |
| // |
| // implementations |
| // |
| template <class T> |
| inline handle<T>::handle() |
| : m_p(0) |
| { |
| } |
| |
| template <class T> |
| inline handle<T>::~handle() |
| { |
| python::xdecref(m_p); |
| } |
| |
| template <class T> |
| inline T* handle<T>::operator->() const |
| { |
| return m_p; |
| } |
| |
| template <class T> |
| inline T& handle<T>::operator*() const |
| { |
| return *m_p; |
| } |
| |
| template <class T> |
| inline T* handle<T>::get() const |
| { |
| return m_p; |
| } |
| |
| template <class T> |
| inline bool handle<T>::operator!() const |
| { |
| return m_p == 0; |
| } |
| |
| template <class T> |
| inline T* handle<T>::release() |
| { |
| T* result = m_p; |
| m_p = 0; |
| return result; |
| } |
| |
| template <class T> |
| inline void handle<T>::reset() |
| { |
| python::xdecref(m_p); |
| m_p = 0; |
| } |
| |
| // Because get_managed_object must return a non-null PyObject*, we |
| // return Py_None if the handle is null. |
| template <class T> |
| inline PyObject* get_managed_object(handle<T> const& h, tag_t) |
| { |
| return h.get() ? python::upcast<PyObject>(h.get()) : Py_None; |
| } |
| |
| }} // namespace boost::python |
| |
| |
| #endif // HANDLE_DWA200269_HPP |