157 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			157 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | // 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 OBJECT_MANAGER_DWA2002614_HPP | ||
|  | # define OBJECT_MANAGER_DWA2002614_HPP | ||
|  | 
 | ||
|  | # include <boost/python/handle.hpp> | ||
|  | # include <boost/python/cast.hpp> | ||
|  | # include <boost/python/converter/pyobject_traits.hpp> | ||
|  | # include <boost/type_traits/object_traits.hpp> | ||
|  | # include <boost/mpl/if.hpp> | ||
|  | # include <boost/python/detail/indirect_traits.hpp> | ||
|  | # include <boost/mpl/bool.hpp> | ||
|  | 
 | ||
|  | // Facilities for dealing with types which always manage Python | ||
|  | // objects. Some examples are object, list, str, et. al. Different | ||
|  | // to_python/from_python conversion rules apply here because in | ||
|  | // contrast to other types which are typically embedded inside a | ||
|  | // Python object, these are wrapped around a Python object. For most | ||
|  | // object managers T, a C++ non-const T reference argument does not | ||
|  | // imply the existence of a T lvalue embedded in the corresponding | ||
|  | // Python argument, since mutating member functions on T actually only | ||
|  | // modify the held Python object. | ||
|  | // | ||
|  | // handle<T> is an object manager, though strictly speaking it should | ||
|  | // not be. In other words, even though mutating member functions of | ||
|  | // hanlde<T> actually modify the handle<T> and not the T object, | ||
|  | // handle<T>& arguments of wrapped functions will bind to "rvalues" | ||
|  | // wrapping the actual Python argument, just as with other object | ||
|  | // manager classes. Making an exception for handle<T> is simply not | ||
|  | // worth the trouble. | ||
|  | // | ||
|  | // borrowed<T> cv* is an object manager so that we can use the general | ||
|  | // to_python mechanisms to convert raw Python object pointers to | ||
|  | // python, without the usual semantic problems of using raw pointers. | ||
|  | 
 | ||
|  | 
 | ||
|  | // Object Manager Concept requirements: | ||
|  | // | ||
|  | //    T is an Object Manager | ||
|  | //    p is a PyObject* | ||
|  | //    x is a T | ||
|  | // | ||
|  | //    * object_manager_traits<T>::is_specialized == true | ||
|  | // | ||
|  | //    * T(detail::borrowed_reference(p)) | ||
|  | //        Manages p without checking its type | ||
|  | // | ||
|  | //    * get_managed_object(x, boost::python::tag) | ||
|  | //        Convertible to PyObject* | ||
|  | // | ||
|  | // Additional requirements if T can be converted from_python: | ||
|  | // | ||
|  | //    * T(object_manager_traits<T>::adopt(p)) | ||
|  | //        steals a reference to p, or throws a TypeError exception if | ||
|  | //        p doesn't have an appropriate type. May assume p is non-null | ||
|  | // | ||
|  | //    * X::check(p) | ||
|  | //        convertible to bool. True iff T(X::construct(p)) will not | ||
|  | //        throw. | ||
|  | 
 | ||
|  | // Forward declarations | ||
|  | // | ||
|  | namespace boost { namespace python | ||
|  | { | ||
|  |   namespace api | ||
|  |   { | ||
|  |     class object;  | ||
|  |   } | ||
|  | }} | ||
|  | 
 | ||
|  | namespace boost { namespace python { namespace converter {  | ||
|  | 
 | ||
|  | 
 | ||
|  | // Specializations for handle<T> | ||
|  | template <class T> | ||
|  | struct handle_object_manager_traits | ||
|  |     : pyobject_traits<typename T::element_type> | ||
|  | { | ||
|  |  private: | ||
|  |   typedef pyobject_traits<typename T::element_type> base; | ||
|  |    | ||
|  |  public: | ||
|  |   BOOST_STATIC_CONSTANT(bool, is_specialized = true); | ||
|  | 
 | ||
|  |   // Initialize with a null_ok pointer for efficiency, bypassing the | ||
|  |   // null check since the source is always non-null. | ||
|  |   static null_ok<typename T::element_type>* adopt(PyObject* p) | ||
|  |   { | ||
|  |       return python::allow_null(base::checked_downcast(p)); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct default_object_manager_traits | ||
|  | { | ||
|  |     BOOST_STATIC_CONSTANT( | ||
|  |         bool, is_specialized = python::detail::is_borrowed_ptr<T>::value | ||
|  |         ); | ||
|  | }; | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct object_manager_traits | ||
|  |     : mpl::if_c< | ||
|  |          is_handle<T>::value | ||
|  |        , handle_object_manager_traits<T> | ||
|  |        , default_object_manager_traits<T> | ||
|  |     >::type | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | // | ||
|  | // Traits for detecting whether a type is an object manager or a | ||
|  | // (cv-qualified) reference to an object manager. | ||
|  | //  | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct is_object_manager | ||
|  |     : mpl::bool_<object_manager_traits<T>::is_specialized> | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct is_reference_to_object_manager | ||
|  |     : mpl::false_ | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct is_reference_to_object_manager<T&> | ||
|  |     : is_object_manager<T> | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct is_reference_to_object_manager<T const&> | ||
|  |     : is_object_manager<T> | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct is_reference_to_object_manager<T volatile&> | ||
|  |     : is_object_manager<T> | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct is_reference_to_object_manager<T const volatile&> | ||
|  |     : is_object_manager<T> | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | }}} // namespace boost::python::converter | ||
|  | 
 | ||
|  | #endif // OBJECT_MANAGER_DWA2002614_HPP |