// 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 |