301 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			301 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								// Copyright David Abrahams 2004.
							 | 
						||
| 
								 | 
							
								// Copyright Stefan Seefeld 2016.
							 | 
						||
| 
								 | 
							
								// 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 boost_python_object_class_metadata_hpp_
							 | 
						||
| 
								 | 
							
								#define boost_python_object_class_metadata_hpp_
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/python/converter/shared_ptr_from_python.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/python/object/inheritance.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/python/object/class_wrapper.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/python/object/make_instance.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/python/object/value_holder.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/python/object/pointer_holder.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/python/object/make_ptr_instance.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/python/detail/force_instantiate.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/python/detail/not_specified.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/python/has_back_reference.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/python/bases.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/add_pointer.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/is_convertible.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/is_polymorphic.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/if.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/eval_if.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/bool.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/or.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/identity.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/for_each.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/placeholders.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/single_view.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/assert.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/is_same.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/is_convertible.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/noncopyable.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/detail/workaround.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost { namespace python { namespace objects { 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOST_PYTHON_DECL
							 | 
						||
| 
								 | 
							
								void copy_class_object(type_info const& src, type_info const& dst);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Support for registering base/derived relationships
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								template <class Derived>
							 | 
						||
| 
								 | 
							
								struct register_base_of
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    template <class Base>
							 | 
						||
| 
								 | 
							
								    inline void operator()(Base*) const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        BOOST_MPL_ASSERT_NOT((is_same<Base,Derived>));
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        // Register the Base class
							 | 
						||
| 
								 | 
							
								        register_dynamic_id<Base>();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Register the up-cast
							 | 
						||
| 
								 | 
							
								        register_conversion<Derived,Base>(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Register the down-cast, if appropriate.
							 | 
						||
| 
								 | 
							
								        this->register_downcast((Base*)0, is_polymorphic<Base>());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								 private:
							 | 
						||
| 
								 | 
							
								    static inline void register_downcast(void*, mpl::false_) {}
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    template <class Base>
							 | 
						||
| 
								 | 
							
								    static inline void register_downcast(Base*, mpl::true_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        register_conversion<Base, Derived>(true);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Preamble of register_class.  Also used for callback classes, which
							 | 
						||
| 
								 | 
							
								// need some registration of their own.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T, class Bases>
							 | 
						||
| 
								 | 
							
								inline void register_shared_ptr_from_python_and_casts(T*, Bases)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // Constructor performs registration
							 | 
						||
| 
								 | 
							
								  python::detail::force_instantiate(converter::shared_ptr_from_python<T, boost::shared_ptr>());
							 | 
						||
| 
								 | 
							
								#if __cplusplus >= 201103L
							 | 
						||
| 
								 | 
							
								  python::detail::force_instantiate(converter::shared_ptr_from_python<T, std::shared_ptr>());
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // register all up/downcasts here.  We're using the alternate
							 | 
						||
| 
								 | 
							
								  // interface to mpl::for_each to avoid an MSVC 6 bug.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  register_dynamic_id<T>();
							 | 
						||
| 
								 | 
							
								  mpl::for_each(register_base_of<T>(), (Bases*)0, (add_pointer<mpl::_>*)0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Helper for choosing the unnamed held_type argument
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								template <class T, class Prev>
							 | 
						||
| 
								 | 
							
								struct select_held_type
							 | 
						||
| 
								 | 
							
								  : mpl::if_<
							 | 
						||
| 
								 | 
							
								        mpl::or_<
							 | 
						||
| 
								 | 
							
								            python::detail::specifies_bases<T>
							 | 
						||
| 
								 | 
							
								          , is_same<T,noncopyable>
							 | 
						||
| 
								 | 
							
								        >
							 | 
						||
| 
								 | 
							
								      , Prev
							 | 
						||
| 
								 | 
							
								      , T
							 | 
						||
| 
								 | 
							
								    >
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <
							 | 
						||
| 
								 | 
							
								    class T // class being wrapped
							 | 
						||
| 
								 | 
							
								  , class X1 // = detail::not_specified
							 | 
						||
| 
								 | 
							
								  , class X2 // = detail::not_specified
							 | 
						||
| 
								 | 
							
								  , class X3 // = detail::not_specified
							 | 
						||
| 
								 | 
							
								>
							 | 
						||
| 
								 | 
							
								struct class_metadata
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // Calculate the unnamed template arguments
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    // held_type_arg -- not_specified, [a class derived from] T or a
							 | 
						||
| 
								 | 
							
								    // smart pointer to [a class derived from] T.  Preserving
							 | 
						||
| 
								 | 
							
								    // not_specified allows us to give class_<T,T> a back-reference.
							 | 
						||
| 
								 | 
							
								    typedef typename select_held_type<
							 | 
						||
| 
								 | 
							
								        X1
							 | 
						||
| 
								 | 
							
								      , typename select_held_type<
							 | 
						||
| 
								 | 
							
								            X2
							 | 
						||
| 
								 | 
							
								          , typename select_held_type<
							 | 
						||
| 
								 | 
							
								                X3
							 | 
						||
| 
								 | 
							
								              , python::detail::not_specified
							 | 
						||
| 
								 | 
							
								            >::type
							 | 
						||
| 
								 | 
							
								        >::type
							 | 
						||
| 
								 | 
							
								    >::type held_type_arg;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // bases
							 | 
						||
| 
								 | 
							
								    typedef typename python::detail::select_bases<
							 | 
						||
| 
								 | 
							
								        X1
							 | 
						||
| 
								 | 
							
								      , typename python::detail::select_bases<
							 | 
						||
| 
								 | 
							
								            X2
							 | 
						||
| 
								 | 
							
								          , typename python::detail::select_bases<
							 | 
						||
| 
								 | 
							
								                X3
							 | 
						||
| 
								 | 
							
								              , python::bases<>
							 | 
						||
| 
								 | 
							
								            >::type
							 | 
						||
| 
								 | 
							
								        >::type
							 | 
						||
| 
								 | 
							
								    >::type bases;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    typedef mpl::or_<
							 | 
						||
| 
								 | 
							
								        is_same<X1,noncopyable>
							 | 
						||
| 
								 | 
							
								      , is_same<X2,noncopyable>
							 | 
						||
| 
								 | 
							
								      , is_same<X3,noncopyable>
							 | 
						||
| 
								 | 
							
								    > is_noncopyable;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // Holder computation.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    // Compute the actual type that will be held in the Holder.
							 | 
						||
| 
								 | 
							
								    typedef typename mpl::if_<
							 | 
						||
| 
								 | 
							
								        is_same<held_type_arg,python::detail::not_specified>, T, held_type_arg
							 | 
						||
| 
								 | 
							
								    >::type held_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Determine if the object will be held by value
							 | 
						||
| 
								 | 
							
								    typedef mpl::bool_<is_convertible<held_type*,T*>::value> use_value_holder;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    // Compute the "wrapped type", that is, if held_type is a smart
							 | 
						||
| 
								 | 
							
								    // pointer, we're talking about the pointee.
							 | 
						||
| 
								 | 
							
								    typedef typename mpl::eval_if<
							 | 
						||
| 
								 | 
							
								        use_value_holder
							 | 
						||
| 
								 | 
							
								      , mpl::identity<held_type>
							 | 
						||
| 
								 | 
							
								      , pointee<held_type>
							 | 
						||
| 
								 | 
							
								    >::type wrapped;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Determine whether to use a "back-reference holder"
							 | 
						||
| 
								 | 
							
								    typedef mpl::bool_<
							 | 
						||
| 
								 | 
							
								        mpl::or_<
							 | 
						||
| 
								 | 
							
								            has_back_reference<T>
							 | 
						||
| 
								 | 
							
								          , is_same<held_type_arg,T>
							 | 
						||
| 
								 | 
							
								          , is_base_and_derived<T,wrapped>
							 | 
						||
| 
								 | 
							
								        >::value
							 | 
						||
| 
								 | 
							
								    > use_back_reference;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Select the holder.
							 | 
						||
| 
								 | 
							
								    typedef typename mpl::eval_if<
							 | 
						||
| 
								 | 
							
								        use_back_reference
							 | 
						||
| 
								 | 
							
								      , mpl::if_<
							 | 
						||
| 
								 | 
							
								            use_value_holder
							 | 
						||
| 
								 | 
							
								          , value_holder_back_reference<T, wrapped>
							 | 
						||
| 
								 | 
							
								          , pointer_holder_back_reference<held_type,T>
							 | 
						||
| 
								 | 
							
								        >
							 | 
						||
| 
								 | 
							
								      , mpl::if_<
							 | 
						||
| 
								 | 
							
								            use_value_holder
							 | 
						||
| 
								 | 
							
								          , value_holder<T>
							 | 
						||
| 
								 | 
							
								          , pointer_holder<held_type,wrapped>
							 | 
						||
| 
								 | 
							
								        >
							 | 
						||
| 
								 | 
							
								    >::type holder;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    inline static void register_() // Register the runtime metadata.
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        class_metadata::register_aux((T*)0);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								 private:
							 | 
						||
| 
								 | 
							
								    template <class T2>
							 | 
						||
| 
								 | 
							
								    inline static void register_aux(python::wrapper<T2>*) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        typedef typename mpl::not_<is_same<T2,wrapped> >::type use_callback;
							 | 
						||
| 
								 | 
							
								        class_metadata::register_aux2((T2*)0, use_callback());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    inline static void register_aux(void*) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        typedef typename is_base_and_derived<T,wrapped>::type use_callback;
							 | 
						||
| 
								 | 
							
								        class_metadata::register_aux2((T*)0, use_callback());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <class T2, class Callback>
							 | 
						||
| 
								 | 
							
								    inline static void register_aux2(T2*, Callback) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
									objects::register_shared_ptr_from_python_and_casts((T2*)0, bases());
							 | 
						||
| 
								 | 
							
								        class_metadata::maybe_register_callback_class((T2*)0, Callback());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        class_metadata::maybe_register_class_to_python((T2*)0, is_noncopyable());
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        class_metadata::maybe_register_pointer_to_python(
							 | 
						||
| 
								 | 
							
								            (T2*)0, (use_value_holder*)0, (use_back_reference*)0);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // Support for converting smart pointers to python
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    inline static void maybe_register_pointer_to_python(...) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
							 | 
						||
| 
								 | 
							
								    inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T const &> >());
							 | 
						||
| 
								 | 
							
								        objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T &> >());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <class T2>
							 | 
						||
| 
								 | 
							
								    inline static void maybe_register_pointer_to_python(T2*, mpl::false_*, mpl::false_*)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        python::detail::force_instantiate(
							 | 
						||
| 
								 | 
							
								            objects::class_value_wrapper<
							 | 
						||
| 
								 | 
							
								                held_type
							 | 
						||
| 
								 | 
							
								              , make_ptr_instance<T2, pointer_holder<held_type, T2> >
							 | 
						||
| 
								 | 
							
								            >()
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
							 | 
						||
| 
								 | 
							
								        // explicit qualification of type_id makes msvc6 happy
							 | 
						||
| 
								 | 
							
								        objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // Support for registering to-python converters
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    inline static void maybe_register_class_to_python(void*, mpl::true_) {}
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <class T2>
							 | 
						||
| 
								 | 
							
								    inline static void maybe_register_class_to_python(T2*, mpl::false_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        python::detail::force_instantiate(class_cref_wrapper<T2, make_instance<T2, holder> >());
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
							 | 
						||
| 
								 | 
							
								        // explicit qualification of type_id makes msvc6 happy
							 | 
						||
| 
								 | 
							
								        objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // Support for registering callback classes
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    inline static void maybe_register_callback_class(void*, mpl::false_) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <class T2>
							 | 
						||
| 
								 | 
							
								    inline static void maybe_register_callback_class(T2*, mpl::true_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
									objects::register_shared_ptr_from_python_and_casts(
							 | 
						||
| 
								 | 
							
								            (wrapped*)0, mpl::single_view<T2>());
							 | 
						||
| 
								 | 
							
								        // explicit qualification of type_id makes msvc6 happy
							 | 
						||
| 
								 | 
							
								        objects::copy_class_object(python::type_id<T2>(), python::type_id<wrapped>());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}}} // namespace boost::python::object
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 |