mirror of
https://github.com/boostorg/python.git
synced 2026-01-25 06:22:15 +00:00
Full virtual function and abstract base support; new class interface.
[SVN r13253]
This commit is contained in:
@@ -7,55 +7,50 @@
|
||||
# define CLASS_DWA200216_HPP
|
||||
|
||||
# include <boost/python/class_fwd.hpp>
|
||||
# include <boost/python/bases.hpp>
|
||||
# include <boost/python/args.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/object/class.hpp>
|
||||
# include <boost/python/object/value_holder_fwd.hpp>
|
||||
# include <boost/python/converter/type_id.hpp>
|
||||
# include <boost/python/detail/wrap_function.hpp>
|
||||
# include <boost/python/detail/member_function_cast.hpp>
|
||||
# include <boost/mpl/type_list.hpp>
|
||||
# include <boost/python/object/class_converters.hpp>
|
||||
# include <boost/type_traits/ice.hpp>
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
# include <boost/mpl/size.hpp>
|
||||
# include <boost/mpl/for_each.hpp>
|
||||
# include <boost/python/detail/type_list.hpp>
|
||||
|
||||
namespace // put some convenience classes into the unnamed namespace for the user
|
||||
{
|
||||
// A type list for specifying bases
|
||||
template < BOOST_MPL_LIST_DEFAULT_PARAMETERS(typename B, ::boost::mpl::null_argument) >
|
||||
struct bases : ::boost::mpl::type_list< BOOST_MPL_LIST_PARAMETERS(B) >::type
|
||||
{};
|
||||
|
||||
// A type list for specifying arguments
|
||||
template < BOOST_MPL_LIST_DEFAULT_PARAMETERS(typename A, ::boost::mpl::null_argument) >
|
||||
struct args : ::boost::mpl::type_list< BOOST_MPL_LIST_PARAMETERS(A) >::type
|
||||
{};
|
||||
}
|
||||
# include <boost/mpl/bool_t.hpp>
|
||||
# include <boost/python/object/select_holder.hpp>
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/utility.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// This is an mpl BinaryMetaFunction object with a runtime behavior,
|
||||
// which is to write the id of the type which is passed as its 2nd
|
||||
// compile-time argument into the iterator pointed to by its runtime
|
||||
// argument
|
||||
struct write_type_id
|
||||
{
|
||||
// The first argument is Ignored because mpl::for_each is still
|
||||
// currently an accumulate (reduce) implementation.
|
||||
template <class Ignored, class T> struct apply
|
||||
{
|
||||
// also an artifact of accumulate-based for_each
|
||||
typedef void type;
|
||||
struct write_type_id;
|
||||
|
||||
template <class T, class Prev = detail::not_specified>
|
||||
struct select_held_type;
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
struct has_noncopyable;
|
||||
|
||||
// Here's the runtime behavior
|
||||
static void execute(converter::undecorated_type_id_t** p)
|
||||
{
|
||||
*(*p)++ = converter::undecorated_type_id<T>();
|
||||
}
|
||||
};
|
||||
};
|
||||
// Register a to_python converter for a class T, depending on the
|
||||
// type of the first (tag) argument. The 2nd argument is a pointer
|
||||
// to the type of holder that must be created. The 3rd argument is a
|
||||
// reference to the Python type object to be created.
|
||||
template <class T, class Holder>
|
||||
static inline void register_copy_constructor(mpl::bool_t<true> const&, Holder*, ref const& obj, T* = 0)
|
||||
{
|
||||
objects::class_wrapper<T,Holder> x(obj);
|
||||
}
|
||||
|
||||
// Tag dispatched to have no effect.
|
||||
template <class T, class Holder>
|
||||
static inline void register_copy_constructor(mpl::bool_t<false> const&, Holder*, ref const&, T* = 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -64,27 +59,24 @@ namespace detail
|
||||
// This is the primary mechanism through which users will expose
|
||||
// C++ classes to Python. The three template arguments are:
|
||||
//
|
||||
// T - The class being exposed to Python
|
||||
//
|
||||
// Bases - An MPL sequence of base classes
|
||||
//
|
||||
// HolderGenerator -
|
||||
// An optional type generator for the "holder" which
|
||||
// maintains the C++ object inside the Python instance. The
|
||||
// default just holds the object "by-value", but other
|
||||
// holders can be substituted which will hold the C++ object
|
||||
// by smart pointer, for example.
|
||||
//
|
||||
template <
|
||||
class T // class being wrapped
|
||||
, class Bases
|
||||
, class HolderGenerator
|
||||
, class X1 // = detail::not_specified
|
||||
, class X2 // = detail::not_specified
|
||||
, class X3 // = detail::not_specified
|
||||
>
|
||||
class class_ : private objects::class_base
|
||||
{
|
||||
typedef class_<T,Bases,HolderGenerator> self;
|
||||
typedef class_<T,X1,X2,X3> self;
|
||||
BOOST_STATIC_CONSTANT(bool, is_copyable = (!detail::has_noncopyable<X1,X2,X3>::value));
|
||||
|
||||
typedef typename detail::select_held_type<
|
||||
X1, typename detail::select_held_type<
|
||||
X2, typename detail::select_held_type<
|
||||
X3
|
||||
>::type>::type>::type held_type;
|
||||
|
||||
public:
|
||||
|
||||
// Automatically derive the class name - only works on some
|
||||
// compilers because type_info::name is sometimes mangled (gcc)
|
||||
class_();
|
||||
@@ -130,7 +122,12 @@ class class_ : private objects::class_base
|
||||
template <class Args>
|
||||
self& def_init(Args const&)
|
||||
{
|
||||
def("__init__", make_constructor<T,Args,HolderGenerator>());
|
||||
def("__init__",
|
||||
make_constructor<Args>(
|
||||
// Using runtime type selection works around a CWPro7 bug.
|
||||
objects::select_holder<T,held_type>((held_type*)0).get()
|
||||
)
|
||||
);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -147,6 +144,12 @@ class class_ : private objects::class_base
|
||||
private: // types
|
||||
typedef objects::class_id class_id;
|
||||
|
||||
typedef typename detail::select_bases<X1
|
||||
, typename detail::select_bases<X2
|
||||
, typename boost::python::detail::select_bases<X3>::type
|
||||
>::type
|
||||
>::type bases;
|
||||
|
||||
// A helper class which will contain an array of id objects to be
|
||||
// passed to the base class constructor
|
||||
struct id_vector
|
||||
@@ -159,50 +162,97 @@ class class_ : private objects::class_base
|
||||
|
||||
// Write the rest of the elements into succeeding positions.
|
||||
class_id* p = ids + 1;
|
||||
mpl::for_each<Bases, void, detail::write_type_id>::execute(&p);
|
||||
mpl::for_each<bases, void, detail::write_type_id>::execute(&p);
|
||||
}
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
std::size_t, size = mpl::size<Bases>::value + 1);
|
||||
std::size_t, size = mpl::size<bases>::value + 1);
|
||||
class_id ids[size];
|
||||
};
|
||||
|
||||
private: // helper functions
|
||||
void initialize_converters();
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
template <class T, class Bases, class HolderGenerator>
|
||||
inline class_<T, Bases, HolderGenerator>::class_()
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline class_<T,X1,X2,X3>::class_()
|
||||
: class_base(typeid(T).name(), id_vector::size, id_vector().ids)
|
||||
{
|
||||
// Bring the class converters into existence. This static object
|
||||
// will survive until the shared library this module lives in is
|
||||
// unloaded (that doesn't happen until Python terminates).
|
||||
static objects::class_converters<T,Bases> converters(object());
|
||||
// register converters
|
||||
objects::register_class_from_python<T,bases>();
|
||||
|
||||
detail::register_copy_constructor<T>(
|
||||
mpl::bool_t<is_copyable>()
|
||||
, objects::select_holder<T,held_type>((held_type*)0).get()
|
||||
, this->object());
|
||||
}
|
||||
|
||||
template <class T, class Bases, class HolderGenerator>
|
||||
inline class_<T, Bases, HolderGenerator>::class_(char const* name)
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline class_<T,X1,X2,X3>::class_(char const* name)
|
||||
: class_base(name, id_vector::size, id_vector().ids)
|
||||
{
|
||||
// Bring the class converters into existence. This static object
|
||||
// will survive until the shared library this module lives in is
|
||||
// unloaded (that doesn't happen until Python terminates).
|
||||
static objects::class_converters<T,Bases> converters(object());
|
||||
// register converters
|
||||
objects::register_class_from_python<T,bases>();
|
||||
|
||||
detail::register_copy_constructor<T>(
|
||||
mpl::bool_t<is_copyable>()
|
||||
, objects::select_holder<T,held_type>((held_type*)0).get()
|
||||
, this->object());
|
||||
}
|
||||
|
||||
template <class T, class Bases, class HolderGenerator>
|
||||
inline ref class_<T, Bases, HolderGenerator>::object() const
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline ref class_<T,X1,X2,X3>::object() const
|
||||
{
|
||||
typedef objects::class_base base;
|
||||
|
||||
return this->base::object();
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// This is an mpl BinaryMetaFunction object with a runtime behavior,
|
||||
// which is to write the id of the type which is passed as its 2nd
|
||||
// compile-time argument into the iterator pointed to by its runtime
|
||||
// argument
|
||||
struct write_type_id
|
||||
{
|
||||
// The first argument is Ignored because mpl::for_each is still
|
||||
// currently an accumulate (reduce) implementation.
|
||||
template <class Ignored, class T> struct apply
|
||||
{
|
||||
// also an artifact of accumulate-based for_each
|
||||
typedef void type;
|
||||
|
||||
// Here's the runtime behavior
|
||||
static void execute(converter::undecorated_type_id_t** p)
|
||||
{
|
||||
*(*p)++ = converter::undecorated_type_id<T>();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
struct has_noncopyable
|
||||
: type_traits::ice_or<
|
||||
is_same<T1,noncopyable>::value
|
||||
, is_same<T2,noncopyable>::value
|
||||
, is_same<T3,noncopyable>::value>
|
||||
{};
|
||||
|
||||
|
||||
template <class T, class Prev>
|
||||
struct select_held_type
|
||||
: mpl::select_type<
|
||||
!(specifies_bases<T>::value | is_same<T,noncopyable>::value)
|
||||
, T
|
||||
, Prev
|
||||
>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CLASS_DWA200216_HPP
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CLASS_FWD_DWA200222_HPP
|
||||
# define CLASS_FWD_DWA200222_HPP
|
||||
# include <boost/python/object/value_holder_fwd.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -16,8 +16,9 @@ namespace detail
|
||||
|
||||
template <
|
||||
class T // class being wrapped
|
||||
, class Bases = detail::empty_list
|
||||
, class HolderGenerator = objects::value_holder_generator<>
|
||||
, class X1 = detail::not_specified
|
||||
, class X2 = detail::not_specified
|
||||
, class X3 = detail::not_specified
|
||||
>
|
||||
class class_;
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ struct arg_tuple_size<R (A0::*)(A1, A2, A3, A4, A5)>
|
||||
|
||||
|
||||
// Metrowerks thinks this creates ambiguities
|
||||
# if !defined(__MWERKS__) || __MWERKS__ > 0x2406
|
||||
# if !defined(__MWERKS__) || __MWERKS__ > 0x2407
|
||||
|
||||
template <class R, class A0>
|
||||
struct arg_tuple_size<R (A0::*)() const>
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
#include <boost/type.hpp>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <boost/type_traits/array_traits.hpp>
|
||||
#include <boost/type_traits/reference_traits.hpp>
|
||||
//
|
||||
// Fix for MSVC's broken typeid() implementation which doesn't strip
|
||||
// decoration. This fix doesn't handle cv-qualified array types. It
|
||||
@@ -62,35 +63,35 @@ inline typeinfo typeid_nonref(boost::type<T>* = 0)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typeinfo typeid_ref(boost::type<T>*, ...)
|
||||
{
|
||||
return typeid_nonref<T>();
|
||||
}
|
||||
|
||||
template <class U, class T>
|
||||
inline typeinfo typeid_ref(boost::type<U>*, T& (*)())
|
||||
inline typeinfo typeid_ref(T&(*)())
|
||||
{
|
||||
return typeid_nonref<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typeinfo typeid_array(bool_t<false>, boost::type<T>* = 0)
|
||||
inline typeinfo array_ref_typeid(bool_t<true>, bool_t<false>, boost::type<T>* = 0)
|
||||
{
|
||||
typedef T (*x)();
|
||||
return typeid_ref((boost::type<T>*)0, x(0));
|
||||
return typeid_ref((T&(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typeinfo typeid_array(bool_t<true>, boost::type<T>* = 0)
|
||||
inline typeinfo array_ref_typeid(bool_t<false>, bool_t<true>, boost::type<T>* = 0)
|
||||
{
|
||||
return typeid_nonref<T>();
|
||||
return typeid_ref((T(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typeinfo array_ref_typeid(bool_t<false>, bool_t<false>, boost::type<T>* = 0)
|
||||
{
|
||||
return typeid_ref((T&(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typeinfo msvc_typeid(boost::type<T>* = 0)
|
||||
{
|
||||
typedef bool_t<is_array<T>::value> tag;
|
||||
return typeid_array(tag(), (boost::type<T>*)0);
|
||||
typedef bool_t<is_array<T>::value> array_tag;
|
||||
typedef bool_t<is_reference<T>::value> ref_tag;
|
||||
return array_ref_typeid(array_tag(), ref_tag(), (boost::type<T>*)0);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
@@ -35,8 +35,8 @@ objects::function* make_function(F f, Policies const& policies)
|
||||
, detail::arg_tuple_size<F>::value);
|
||||
}
|
||||
|
||||
template <class T, class ArgList, class Generator>
|
||||
objects::function* make_constructor(T* = 0, ArgList* = 0, Generator* = 0)
|
||||
template <class ArgList, class Holder>
|
||||
objects::function* make_constructor(Holder* = 0, ArgList* = 0)
|
||||
{
|
||||
enum { nargs = mpl::size<ArgList>::value };
|
||||
|
||||
@@ -44,7 +44,7 @@ objects::function* make_constructor(T* = 0, ArgList* = 0, Generator* = 0)
|
||||
objects::py_function(
|
||||
::boost::bind<PyObject*>(detail::caller(),
|
||||
objects::make_holder<nargs>
|
||||
::template apply<T,Generator,ArgList>::execute
|
||||
::template apply<Holder,ArgList>::execute
|
||||
, _1, _2, default_call_policies()))
|
||||
, nargs + 1);
|
||||
}
|
||||
|
||||
@@ -11,27 +11,10 @@
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/object/find_instance.hpp>
|
||||
# include <boost/python/object/inheritance.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
// Instantiating this class brings into existence all converters
|
||||
// associated with a class Bases is expected to be an mpl sequence of
|
||||
// base types.
|
||||
template <class Derived, class Bases>
|
||||
struct class_converters
|
||||
{
|
||||
public: // member functions
|
||||
// Constructor takes the python class object associated with T
|
||||
class_converters(ref const& python_class);
|
||||
|
||||
private: // data members
|
||||
class_wrapper<Derived> m_wrapper;
|
||||
};
|
||||
|
||||
//
|
||||
// Implementation details
|
||||
//
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// register_base_of<T> -
|
||||
@@ -86,9 +69,11 @@ struct register_base_of
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Brings into existence all converters associated with a class Bases
|
||||
// is expected to be an mpl sequence of base types.
|
||||
template <class Derived, class Bases>
|
||||
class_converters<Derived,Bases>::class_converters(ref const& type_object)
|
||||
: m_wrapper(type_object)
|
||||
inline void register_class_from_python(Derived* = 0, Bases* = 0)
|
||||
{
|
||||
(void)instance_finder<Derived>::registration;
|
||||
|
||||
|
||||
@@ -6,15 +6,14 @@
|
||||
#ifndef CLASS_WRAPPER_DWA20011221_HPP
|
||||
# define CLASS_WRAPPER_DWA20011221_HPP
|
||||
|
||||
# include <boost/python/object/value_holder.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/to_python_converter.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
template <class T>
|
||||
template <class T, class Holder>
|
||||
struct class_wrapper
|
||||
: to_python_converter<T, class_wrapper<T> >
|
||||
: to_python_converter<T,class_wrapper<T,Holder> >
|
||||
{
|
||||
class_wrapper(ref const& type_)
|
||||
: m_class_object_keeper(type_)
|
||||
@@ -39,7 +38,7 @@ struct class_wrapper
|
||||
|
||||
// Build a value_holder to contain the object using the copy
|
||||
// constructor
|
||||
value_holder<T>* p = new value_holder<T>(raw_result, cref(x));
|
||||
Holder* p = new Holder(raw_result, cref(x));
|
||||
|
||||
// Install it in the instance
|
||||
p->install(raw_result);
|
||||
@@ -53,8 +52,8 @@ struct class_wrapper
|
||||
static PyTypeObject* m_class_object;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
PyTypeObject* class_wrapper<T>::m_class_object;
|
||||
template <class T, class Holder>
|
||||
PyTypeObject* class_wrapper<T,Holder>::m_class_object;
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#ifndef FIND_INSTANCE_DWA2002312_HPP
|
||||
# define FIND_INSTANCE_DWA2002312_HPP
|
||||
|
||||
# include <boost/python/converter/type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
// Given an undecorated type_id, find the instance data which
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
# include <boost/python/object/forward.hpp>
|
||||
# include <boost/python/object/class.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/mpl/apply.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
@@ -19,14 +18,13 @@ template <int nargs> struct make_holder;
|
||||
template <>
|
||||
struct make_holder<0>
|
||||
{
|
||||
template <class T, class Generator, class ArgList>
|
||||
template <class Holder, class ArgList>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::apply1<Generator,T>::type holder;
|
||||
static void execute(
|
||||
PyObject* p)
|
||||
{
|
||||
(new holder(p))->install(p);
|
||||
(new Holder(p))->install(p);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -35,10 +33,9 @@ struct make_holder<0>
|
||||
template <>
|
||||
struct make_holder<1>
|
||||
{
|
||||
template <class T, class Generator, class ArgList>
|
||||
template <class Holder, class ArgList>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::apply1<Generator,T>::type holder;
|
||||
typedef typename mpl::at<0,ArgList>::type t0;
|
||||
typedef typename forward<t0>::type f0;
|
||||
|
||||
@@ -46,7 +43,7 @@ struct make_holder<1>
|
||||
PyObject* p
|
||||
, t0 a0)
|
||||
{
|
||||
(new holder(p, f0(a0)))->install(p);
|
||||
(new Holder(p, f0(a0)))->install(p);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -54,10 +51,9 @@ struct make_holder<1>
|
||||
template <>
|
||||
struct make_holder<2>
|
||||
{
|
||||
template <class T, class Generator, class ArgList>
|
||||
template <class Holder, class ArgList>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::apply1<Generator,T>::type holder;
|
||||
typedef typename mpl::at<0,ArgList>::type t0;
|
||||
typedef typename forward<t0>::type f0;
|
||||
typedef typename mpl::at<1,ArgList>::type t1;
|
||||
@@ -66,7 +62,7 @@ struct make_holder<2>
|
||||
static void execute(
|
||||
PyObject* p, t0 a0, t1 a1)
|
||||
{
|
||||
(new holder(p, f0(a0), f1(a1)))->install(p);
|
||||
(new Holder(p, f0(a0), f1(a1)))->install(p);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -74,10 +70,9 @@ struct make_holder<2>
|
||||
template <>
|
||||
struct make_holder<3>
|
||||
{
|
||||
template <class T, class Generator, class ArgList>
|
||||
template <class Holder, class ArgList>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::apply1<Generator,T>::type holder;
|
||||
typedef typename mpl::at<0,ArgList>::type t0;
|
||||
typedef typename forward<t0>::type f0;
|
||||
typedef typename mpl::at<1,ArgList>::type t1;
|
||||
@@ -88,7 +83,7 @@ struct make_holder<3>
|
||||
static void execute(
|
||||
PyObject* p, t0 a0, t1 a1, t2 a2)
|
||||
{
|
||||
(new holder(p, f0(a0), f1(a1), f2(a2)))->install(p);
|
||||
(new Holder(p, f0(a0), f1(a1), f2(a2)))->install(p);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -96,10 +91,9 @@ struct make_holder<3>
|
||||
template <>
|
||||
struct make_holder<4>
|
||||
{
|
||||
template <class T, class Generator, class ArgList>
|
||||
template <class Holder, class ArgList>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::apply1<Generator,T>::type holder;
|
||||
typedef typename mpl::at<0,ArgList>::type t0;
|
||||
typedef typename forward<t0>::type f0;
|
||||
typedef typename mpl::at<1,ArgList>::type t1;
|
||||
@@ -112,7 +106,7 @@ struct make_holder<4>
|
||||
static void execute(
|
||||
PyObject* p, t0 a0, t1 a1, t2 a2, t3 a3)
|
||||
{
|
||||
(new holder(p, f0(a0), f1(a1), f2(a2), f3(a3)))->install(p);
|
||||
(new Holder(p, f0(a0), f1(a1), f2(a2), f3(a3)))->install(p);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -120,10 +114,9 @@ struct make_holder<4>
|
||||
template <>
|
||||
struct make_holder<5>
|
||||
{
|
||||
template <class T, class Generator, class ArgList>
|
||||
template <class Holder, class ArgList>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::apply1<Generator,T>::type holder;
|
||||
typedef typename mpl::at<0,ArgList>::type t0;
|
||||
typedef typename forward<t0>::type f0;
|
||||
typedef typename mpl::at<1,ArgList>::type t1;
|
||||
@@ -138,7 +131,7 @@ struct make_holder<5>
|
||||
static void execute(
|
||||
PyObject* p, t0 a0, t1 a1, t2 a2, t3 a3, t4 a4)
|
||||
{
|
||||
(new holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4)))->install(p);
|
||||
(new Holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4)))->install(p);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -146,10 +139,9 @@ struct make_holder<5>
|
||||
template <>
|
||||
struct make_holder<6>
|
||||
{
|
||||
template <class T, class Generator, class ArgList>
|
||||
template <class Holder, class ArgList>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::apply1<Generator,T>::type holder;
|
||||
typedef typename mpl::at<0,ArgList>::type t0;
|
||||
typedef typename forward<t0>::type f0;
|
||||
typedef typename mpl::at<1,ArgList>::type t1;
|
||||
@@ -166,7 +158,7 @@ struct make_holder<6>
|
||||
static void execute(
|
||||
PyObject* p, t0 a0, t1 a1, t2 a2, t3 a3, t4 a4, t5 a5)
|
||||
{
|
||||
(new holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4), f5(a5)))->install(p);
|
||||
(new Holder(p, f0(a0), f1(a1), f2(a2), f3(a3), f4(a4), f5(a5)))->install(p);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/mpl/select_type.hpp>
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/python/detail/pointee.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
@@ -147,81 +148,83 @@ struct pointer_holder : instance_holder
|
||||
Pointer m_p;
|
||||
};
|
||||
|
||||
template <class Pointer, class Value, class BackReferenceType>
|
||||
template <class Pointer, class Value>
|
||||
struct pointer_holder_back_reference : instance_holder
|
||||
{
|
||||
private:
|
||||
typedef typename python::detail::pointee<Pointer>::type held_type;
|
||||
public:
|
||||
|
||||
pointer_holder_back_reference(Pointer);
|
||||
|
||||
// Forward construction to the held object
|
||||
pointer_holder_back_reference(PyObject* p)
|
||||
: m_p(new BackReferenceType(p)) {
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
: m_p(new held_type(p)) {
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class A1>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
))
|
||||
{
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
template <class A1, class A2>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
, (typename unwrap_reference<A2>::type&)(a2)
|
||||
))
|
||||
{
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
, (typename unwrap_reference<A2>::type&)(a2)
|
||||
, (typename unwrap_reference<A3>::type&)(a3)
|
||||
))
|
||||
{
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
, (typename unwrap_reference<A2>::type&)(a2)
|
||||
, (typename unwrap_reference<A3>::type&)(a3)
|
||||
, (typename unwrap_reference<A4>::type&)(a4)
|
||||
))
|
||||
{
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
, (typename unwrap_reference<A2>::type&)(a2)
|
||||
, (typename unwrap_reference<A3>::type&)(a3)
|
||||
, (typename unwrap_reference<A4>::type&)(a4)
|
||||
, (typename unwrap_reference<A5>::type&)(a5)
|
||||
)) {
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
, (typename unwrap_reference<A2>::type&)(a2)
|
||||
, (typename unwrap_reference<A3>::type&)(a3)
|
||||
@@ -229,13 +232,13 @@ struct pointer_holder_back_reference : instance_holder
|
||||
, (typename unwrap_reference<A5>::type&)(a5)
|
||||
, (typename unwrap_reference<A6>::type&)(a6)
|
||||
)) {
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
, (typename unwrap_reference<A2>::type&)(a2)
|
||||
, (typename unwrap_reference<A3>::type&)(a3)
|
||||
@@ -245,13 +248,13 @@ struct pointer_holder_back_reference : instance_holder
|
||||
, (typename unwrap_reference<A7>::type&)(a7)
|
||||
))
|
||||
{
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
, (typename unwrap_reference<A2>::type&)(a2)
|
||||
, (typename unwrap_reference<A3>::type&)(a3)
|
||||
@@ -262,13 +265,13 @@ struct pointer_holder_back_reference : instance_holder
|
||||
, (typename unwrap_reference<A8>::type&)(a8)
|
||||
))
|
||||
{
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
, (typename unwrap_reference<A2>::type&)(a2)
|
||||
, (typename unwrap_reference<A3>::type&)(a3)
|
||||
@@ -280,13 +283,13 @@ struct pointer_holder_back_reference : instance_holder
|
||||
, (typename unwrap_reference<A9>::type&)(a9)
|
||||
))
|
||||
{
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
pointer_holder_back_reference(PyObject* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10)
|
||||
: m_p(new BackReferenceType(p
|
||||
: m_p(new held_type(p
|
||||
, (typename unwrap_reference<A1>::type&)(a1)
|
||||
, (typename unwrap_reference<A2>::type&)(a2)
|
||||
, (typename unwrap_reference<A3>::type&)(a3)
|
||||
@@ -299,7 +302,7 @@ struct pointer_holder_back_reference : instance_holder
|
||||
, (typename unwrap_reference<A10>::type&)(a10)
|
||||
))
|
||||
{
|
||||
(void)instance_finder<BackReferenceType>::registration;
|
||||
(void)instance_finder<held_type>::registration;
|
||||
}
|
||||
|
||||
|
||||
@@ -310,81 +313,18 @@ struct pointer_holder_back_reference : instance_holder
|
||||
Pointer m_p;
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
// back to namespace boost for this forward declaration
|
||||
namespace boost
|
||||
{
|
||||
template <class T> class shared_ptr;
|
||||
}
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
struct shared_ptr_generator
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef boost::shared_ptr<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
struct no_back_reference;
|
||||
|
||||
// Workaround lack of partial specialization
|
||||
namespace detail
|
||||
{
|
||||
template <class BackReferenceType, class PointerGenerator>
|
||||
struct pointer_holder_back_reference_generator
|
||||
{
|
||||
template <class Held>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::apply1<
|
||||
PointerGenerator,BackReferenceType
|
||||
>::type pointer;
|
||||
|
||||
typedef pointer_holder_back_reference<pointer,Held,BackReferenceType> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <class PointerGenerator>
|
||||
struct plain_pointer_holder_generator
|
||||
{
|
||||
template <class Held>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::apply1<
|
||||
PointerGenerator,Held
|
||||
>::type pointer;
|
||||
|
||||
typedef pointer_holder<pointer, Held> type;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// A generator metafunction which can be passed to make_holder
|
||||
// PointerGenerator should be another generator metafunction which
|
||||
// makes the appropriate (smart) pointer type to hold the argument to
|
||||
// pointer_holder_generator.
|
||||
template <class PointerGenerator, class BackReferenceType = no_back_reference>
|
||||
struct pointer_holder_generator
|
||||
: mpl::select_type<
|
||||
is_same<BackReferenceType,no_back_reference>::value
|
||||
, detail::plain_pointer_holder_generator<
|
||||
PointerGenerator>
|
||||
, detail::pointer_holder_back_reference_generator<
|
||||
BackReferenceType,PointerGenerator>
|
||||
>::type
|
||||
{
|
||||
};
|
||||
|
||||
template <class Pointer, class Value>
|
||||
pointer_holder<Pointer,Value>::pointer_holder(Pointer p)
|
||||
: m_p(p)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Pointer, class Value>
|
||||
pointer_holder_back_reference<Pointer,Value>::pointer_holder_back_reference(Pointer p)
|
||||
: m_p(p)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Pointer, class Value>
|
||||
void* pointer_holder<Pointer, Value>::holds(converter::undecorated_type_id_t dst_t)
|
||||
{
|
||||
@@ -396,6 +336,20 @@ void* pointer_holder<Pointer, Value>::holds(converter::undecorated_type_id_t dst
|
||||
: find_dynamic_type(&*this->m_p, src_t, dst_t);
|
||||
}
|
||||
|
||||
template <class Pointer, class Value>
|
||||
void* pointer_holder_back_reference<Pointer, Value>::holds(converter::undecorated_type_id_t dst_t)
|
||||
{
|
||||
if (dst_t == converter::undecorated_type_id<Pointer>())
|
||||
return &this->m_p;
|
||||
|
||||
if (dst_t == converter::undecorated_type_id<held_type>())
|
||||
return &*this->m_p;
|
||||
|
||||
converter::type_id_t src_t = converter::undecorated_type_id<Value>();
|
||||
Value* p = &*this->m_p;
|
||||
return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
#endif // POINTER_HOLDER_DWA20011215_HPP
|
||||
|
||||
70
include/boost/python/object/select_holder.hpp
Normal file
70
include/boost/python/object/select_holder.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef SELECT_HOLDER_DWA2002322_HPP
|
||||
# define SELECT_HOLDER_DWA2002322_HPP
|
||||
|
||||
# include <boost/python/has_back_reference.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
# include <boost/python/detail/pointee.hpp>
|
||||
# include <boost/python/detail/if_else.hpp>
|
||||
# include <boost/python/object/value_holder.hpp>
|
||||
# include <boost/python/object/pointer_holder.hpp>
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/mpl/select_type.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T, class Held>
|
||||
struct select_value_holder
|
||||
{
|
||||
typedef typename mpl::select_type<
|
||||
(!is_same<T,Held>::value) | has_back_reference<T>::value
|
||||
, value_holder_back_reference<T,Held>
|
||||
, value_holder<T>
|
||||
>::type holder;
|
||||
|
||||
static holder* get() { return 0; }
|
||||
};
|
||||
|
||||
template <class T,class Ptr>
|
||||
struct select_pointer_holder
|
||||
{
|
||||
typedef typename python::detail::pointee<Ptr>::type pointee;
|
||||
|
||||
typedef typename mpl::select_type<
|
||||
(!is_same<pointee,T>::value) | has_back_reference<T>::value
|
||||
, pointer_holder_back_reference<Ptr,T>
|
||||
, pointer_holder<Ptr,T>
|
||||
>::type holder;
|
||||
|
||||
static holder* get() { return 0; }
|
||||
};
|
||||
}
|
||||
|
||||
template <class T, class NotSpecified>
|
||||
inline detail::select_value_holder<T,T> select_holder(python::detail::not_specified*, T* = 0, NotSpecified* = 0)
|
||||
{
|
||||
return detail::select_value_holder<T,T>();
|
||||
}
|
||||
|
||||
template <class T, class Held>
|
||||
inline detail::select_value_holder<T, Held> select_holder(T*, Held* = 0)
|
||||
{
|
||||
return detail::select_value_holder<T, Held>();
|
||||
}
|
||||
|
||||
|
||||
template <class T, class Ptr>
|
||||
detail::select_pointer_holder<T,Ptr> select_holder(void*, Ptr* = 0, T* = 0)
|
||||
{
|
||||
return detail::select_pointer_holder<T,Ptr>();
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
#endif // SELECT_HOLDER_DWA2002322_HPP
|
||||
@@ -142,7 +142,7 @@ struct value_holder : instance_holder
|
||||
Held m_held;
|
||||
};
|
||||
|
||||
template <class Held,class BackReferenceType>
|
||||
template <class Held, class BackReferenceType>
|
||||
struct value_holder_back_reference : instance_holder
|
||||
{
|
||||
// Forward construction to the held object
|
||||
@@ -301,27 +301,6 @@ struct value_holder_back_reference : instance_holder
|
||||
BackReferenceType m_held;
|
||||
};
|
||||
|
||||
// A generator metafunction which can be passed to make_holder
|
||||
template <>
|
||||
struct value_holder_generator<no_back_reference>
|
||||
{
|
||||
template <class Held>
|
||||
struct apply
|
||||
{
|
||||
typedef value_holder<Held> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <class BackReferenceType>
|
||||
struct value_holder_generator
|
||||
{
|
||||
template <class Held>
|
||||
struct apply
|
||||
{
|
||||
typedef value_holder_back_reference<Held,BackReferenceType> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <class Held>
|
||||
void* value_holder<Held>::holds(converter::undecorated_type_id_t dst_t)
|
||||
{
|
||||
|
||||
15
test/Jamfile
15
test/Jamfile
@@ -68,6 +68,20 @@ unit-test pointer_type_id_test
|
||||
unit-test member_function_cast
|
||||
: member_function_cast.cpp : <include>$(BOOST_ROOT) ;
|
||||
|
||||
unit-test bases
|
||||
: bases.cpp : <include>$(BOOST_ROOT) ;
|
||||
|
||||
unit-test if_else
|
||||
: if_else.cpp : <include>$(BOOST_ROOT) ;
|
||||
|
||||
unit-test pointee
|
||||
: pointee.cpp : <include>$(BOOST_ROOT) ;
|
||||
|
||||
unit-test select_holder
|
||||
: select_holder.cpp
|
||||
: <include>$(BOOST_ROOT) <define>BOOST_PYTHON_STATIC_LIB $(PYTHON_PROPERTIES)
|
||||
;
|
||||
|
||||
unit-test select_from_python_test
|
||||
: select_from_python_test.cpp
|
||||
../src/converter/type_id.cpp
|
||||
@@ -77,3 +91,4 @@ unit-test select_from_python_test
|
||||
$(PYTHON_V1_PROPERTIES)
|
||||
;
|
||||
|
||||
|
||||
|
||||
13
test/m1.cpp
13
test/m1.cpp
@@ -201,6 +201,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
|
||||
{
|
||||
using namespace boost::python;
|
||||
using boost::mpl::type_list;
|
||||
using boost::shared_ptr;
|
||||
|
||||
simple_to_python();
|
||||
|
||||
@@ -219,10 +220,6 @@ BOOST_PYTHON_MODULE_INIT(m1)
|
||||
|
||||
module m1("m1");
|
||||
|
||||
typedef boost::python::objects::pointer_holder_generator<
|
||||
boost::python::objects::shared_ptr_generator
|
||||
> use_shared_ptr;
|
||||
|
||||
m1
|
||||
// Insert the metaclass for all extension classes
|
||||
.setattr("xclass", boost::python::objects::class_metatype())
|
||||
@@ -251,7 +248,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
|
||||
.def("take_d", take_d)
|
||||
|
||||
.add(
|
||||
class_<A, bases<>, use_shared_ptr>("A")
|
||||
class_<A, shared_ptr<A> >("A")
|
||||
.def_init()
|
||||
.def("name", &A::name)
|
||||
)
|
||||
@@ -262,13 +259,13 @@ BOOST_PYTHON_MODULE_INIT(m1)
|
||||
// or "C" below if we make them part of the same chain
|
||||
m1
|
||||
.add(
|
||||
class_<B,bases<A>, use_shared_ptr>("B")
|
||||
class_<B,bases<A>, shared_ptr<B> >("B")
|
||||
.def_init()
|
||||
.def("name", &B::name)
|
||||
)
|
||||
|
||||
.add(
|
||||
class_<C,bases<A>, use_shared_ptr>("C")
|
||||
class_<C,bases<A>, shared_ptr<C> >("C")
|
||||
.def_init()
|
||||
.def("name", &C::name)
|
||||
)
|
||||
@@ -276,7 +273,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
|
||||
|
||||
m1
|
||||
.add(
|
||||
class_<D,bases<B,C>, use_shared_ptr>("D")
|
||||
class_<D,shared_ptr<D>, bases<B,C> >("D")
|
||||
.def_init()
|
||||
.def("name", &D::name)
|
||||
)
|
||||
|
||||
77
test/select_holder.cpp
Normal file
77
test/select_holder.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#include <boost/python/object/select_holder.hpp>
|
||||
#include <boost/python/has_back_reference.hpp>
|
||||
#include <boost/python/detail/not_specified.hpp>
|
||||
#include <memory>
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
struct BR {};
|
||||
|
||||
struct Base {};
|
||||
struct Derived : Base {};
|
||||
|
||||
namespace boost { namespace python
|
||||
{
|
||||
// specialization
|
||||
template <>
|
||||
struct has_back_reference<BR>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
}} // namespace boost::python
|
||||
|
||||
template <class T, class U>
|
||||
void assert_same(U* = 0, T* = 0)
|
||||
{
|
||||
BOOST_TEST((boost::is_same<T,U>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T,U>::value));
|
||||
|
||||
}
|
||||
|
||||
template <class T, class Held, class Holder>
|
||||
void assert_holder(T* = 0, Held* = 0, Holder* = 0)
|
||||
{
|
||||
assert_same<Holder>(boost::python::objects::select_holder<T,Held>((Held*)0).get());
|
||||
}
|
||||
|
||||
int test_main(int, char * [])
|
||||
{
|
||||
using namespace boost::python::detail;
|
||||
using namespace boost::python::objects;
|
||||
|
||||
assert_holder<Base,not_specified,value_holder<Base> >();
|
||||
|
||||
assert_holder<BR,not_specified,value_holder_back_reference<BR,BR> >();
|
||||
assert_holder<Base,Base,value_holder<Base> >();
|
||||
assert_holder<BR,BR,value_holder_back_reference<BR,BR> >();
|
||||
|
||||
assert_holder<Base,Derived
|
||||
,value_holder_back_reference<Base,Derived> >();
|
||||
|
||||
assert_holder<Base,std::auto_ptr<Base>
|
||||
,pointer_holder<std::auto_ptr<Base>,Base> >();
|
||||
|
||||
assert_holder<Base,std::auto_ptr<Derived>
|
||||
,pointer_holder_back_reference<std::auto_ptr<Derived>,Base> >();
|
||||
|
||||
assert_holder<BR,std::auto_ptr<BR>
|
||||
,pointer_holder_back_reference<std::auto_ptr<BR>,BR> > ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ <= 3
|
||||
// This definition is needed for MinGW 2.95.2 for some reason
|
||||
namespace boost { namespace python
|
||||
{
|
||||
bool handle_exception_impl(boost::function0<void>) { return false; }
|
||||
}}
|
||||
#endif
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/returning.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
@@ -66,6 +67,10 @@ struct concrete_callback : concrete
|
||||
: concrete(x), self(p)
|
||||
{}
|
||||
|
||||
concrete_callback(PyObject* p, concrete const& x)
|
||||
: concrete(x), self(p)
|
||||
{}
|
||||
|
||||
int f(Y const& y)
|
||||
{
|
||||
return returning<int>::call_method(self, "f", boost::ref(y));
|
||||
@@ -85,26 +90,21 @@ BOOST_PYTHON_MODULE_INIT(virtual_functions_ext)
|
||||
{
|
||||
module("virtual_functions_ext")
|
||||
.add(
|
||||
class_<concrete, bases<>, objects::value_holder_generator<concrete_callback> >("concrete")
|
||||
class_<concrete, concrete_callback>("concrete")
|
||||
.def_init(args<int>())
|
||||
.def("value", &concrete::value)
|
||||
.def("set", &concrete::set)
|
||||
.def("call_f", &concrete::call_f)
|
||||
.def("f", &concrete_callback::f_impl))
|
||||
|
||||
#if 0
|
||||
.add(
|
||||
class_<abstract, bases<>
|
||||
, objects::pointer_holder_generator<
|
||||
boost::python::objects::shared_ptr_generator
|
||||
, abstract_callback>
|
||||
class_<abstract, boost::noncopyable, boost::shared_ptr<abstract_callback>
|
||||
>("abstract")
|
||||
|
||||
.def_init(args<int>())
|
||||
.def("value", &abstract::value)
|
||||
.def("call_f", &abstract::call_f)
|
||||
.def("set", &abstract::set))
|
||||
#endif
|
||||
|
||||
.add(
|
||||
class_<Y>("Y")
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
>>> class C2(concrete):
|
||||
... pass
|
||||
|
||||
<<<>>> class A1(abstract):
|
||||
<<<... def f(self, y):
|
||||
<<<... return abstract.f(self, Y(-y.value()))
|
||||
<<<
|
||||
<<<>>> class A2(abstract):
|
||||
<<<... pass
|
||||
<<<
|
||||
>>> class A1(abstract):
|
||||
... def f(self, y):
|
||||
... return y.value() * 2
|
||||
|
||||
>>> class A2(abstract):
|
||||
... pass
|
||||
|
||||
|
||||
>>> y1 = Y(16)
|
||||
>>> y2 = Y(17)
|
||||
@@ -24,33 +24,35 @@
|
||||
#
|
||||
# Test abstract with f overridden
|
||||
#
|
||||
<<<>>> a1 = A1(42)
|
||||
<<<>>> a1.value()
|
||||
<<<42
|
||||
<<<
|
||||
<<<# Call f indirectly from C++
|
||||
<<<>>> a1.call_f(y1)
|
||||
<<<-16
|
||||
<<<
|
||||
<<<# Call f directly from Python
|
||||
<<<>>> a1.f(y2)
|
||||
<<<-17
|
||||
<<<
|
||||
<<<#
|
||||
<<<# Test abstract with f not overridden
|
||||
<<<#
|
||||
<<<>>> a2 = A2(42)
|
||||
<<<>>> A2.value()
|
||||
<<<42
|
||||
<<<
|
||||
<<<# Call f indirectly from C++
|
||||
<<<>>> c1.call_f(y1)
|
||||
<<<16
|
||||
<<<
|
||||
<<<# Call f directly from Python
|
||||
<<<>>> c1.f(y2)
|
||||
<<<17
|
||||
<<<
|
||||
>>> a1 = A1(42)
|
||||
>>> a1.value()
|
||||
42
|
||||
|
||||
# Call f indirectly from C++
|
||||
>>> a1.call_f(y1)
|
||||
32
|
||||
|
||||
# Call f directly from Python
|
||||
>>> a1.f(y2)
|
||||
34
|
||||
|
||||
#
|
||||
# Test abstract with f not overridden
|
||||
#
|
||||
>>> a2 = A2(42)
|
||||
>>> a2.value()
|
||||
42
|
||||
|
||||
# Call f indirectly from C++
|
||||
>>> try: a2.call_f(y1)
|
||||
... except AttributeError: pass
|
||||
... else: print 'no exception'
|
||||
|
||||
# Call f directly from Python
|
||||
>>> try: a2.call_f(y2)
|
||||
... except AttributeError: pass
|
||||
... else: print 'no exception'
|
||||
|
||||
############# Concrete Tests ############
|
||||
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user