mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
New-style polymorphism
[SVN r24083]
This commit is contained in:
@@ -53,6 +53,7 @@ if [ check-python-config ]
|
||||
object/iterator.cpp
|
||||
object_protocol.cpp
|
||||
object_operators.cpp
|
||||
wrapper.cpp
|
||||
;
|
||||
|
||||
dll boost_python
|
||||
|
||||
@@ -32,6 +32,12 @@ struct base_type_traits<PyTypeObject>
|
||||
typedef PyObject type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct base_type_traits<PyMethodObject>
|
||||
{
|
||||
typedef PyObject type;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BASE_TYPE_TRAITS_DWA2002614_HPP
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
# include <boost/python/detail/unwrap_type_id.hpp>
|
||||
# include <boost/python/detail/unwrap_wrapper.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
@@ -151,7 +153,7 @@ namespace detail
|
||||
// This is the primary mechanism through which users will expose
|
||||
// C++ classes to Python.
|
||||
template <
|
||||
class T // class being wrapped
|
||||
class W // class being wrapped
|
||||
, class X1 // = detail::not_specified
|
||||
, class X2 // = detail::not_specified
|
||||
, class X3 // = detail::not_specified
|
||||
@@ -160,9 +162,9 @@ class class_ : public objects::class_base
|
||||
{
|
||||
public: // types
|
||||
typedef objects::class_base base;
|
||||
typedef class_<T,X1,X2,X3> self;
|
||||
typedef typename objects::class_metadata<T,X1,X2,X3> metadata;
|
||||
typedef T wrapped_type;
|
||||
typedef class_<W,X1,X2,X3> self;
|
||||
typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
|
||||
typedef W wrapped_type;
|
||||
|
||||
private: // types
|
||||
|
||||
@@ -175,7 +177,7 @@ class class_ : public objects::class_base
|
||||
id_vector()
|
||||
{
|
||||
// Stick the derived class id into the first element of the array
|
||||
ids[0] = type_id<T>();
|
||||
ids[0] = detail::unwrap_type_id((W*)0, (W*)0);
|
||||
|
||||
// Write the rest of the elements into succeeding positions.
|
||||
type_info* p = ids + 1;
|
||||
@@ -231,7 +233,9 @@ class class_ : public objects::class_base
|
||||
template <class F>
|
||||
self& def(char const* name, F f)
|
||||
{
|
||||
this->def_impl(name, f, detail::def_helper<char const*>(0), &f);
|
||||
this->def_impl(
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, name, f, detail::def_helper<char const*>(0), &f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -250,9 +254,10 @@ class class_ : public objects::class_base
|
||||
// def(name, function, doc_string, policy)
|
||||
|
||||
this->def_impl(
|
||||
name, fn
|
||||
, detail::def_helper<A1,A2>(a1,a2)
|
||||
, &fn);
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, name, fn
|
||||
, detail::def_helper<A1,A2>(a1,a2)
|
||||
, &fn);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -261,9 +266,10 @@ class class_ : public objects::class_base
|
||||
self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3)
|
||||
{
|
||||
this->def_impl(
|
||||
name, fn
|
||||
, detail::def_helper<A1,A2,A3>(a1,a2,a3)
|
||||
, &fn);
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, name, fn
|
||||
, detail::def_helper<A1,A2,A3>(a1,a2,a3)
|
||||
, &fn);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -371,7 +377,8 @@ class class_ : public objects::class_base
|
||||
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
|
||||
|
||||
return this->make_fn_impl(
|
||||
f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -381,32 +388,33 @@ class class_ : public objects::class_base
|
||||
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
|
||||
|
||||
return this->make_fn_impl(
|
||||
f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
object make_fn_impl(F const& f, mpl::false_, void*, mpl::false_)
|
||||
template <class T, class F>
|
||||
object make_fn_impl(T*, F const& f, mpl::false_, void*, mpl::false_)
|
||||
{
|
||||
return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
object make_fn_impl(D B::*pm_, mpl::false_, char*, mpl::true_)
|
||||
template <class T, class D, class B>
|
||||
object make_fn_impl(T*, D B::*pm_, mpl::false_, char*, mpl::true_)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return python::make_getter(pm);
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
object make_fn_impl(D B::*pm_, mpl::false_, int*, mpl::true_)
|
||||
template <class T, class D, class B>
|
||||
object make_fn_impl(T*, D B::*pm_, mpl::false_, int*, mpl::true_)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return python::make_setter(pm);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
object make_fn_impl(F const& x, mpl::true_, void*, mpl::false_)
|
||||
template <class T, class F>
|
||||
object make_fn_impl(T*, F const& x, mpl::true_, void*, mpl::false_)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
@@ -462,9 +470,10 @@ class class_ : public objects::class_base
|
||||
// generic visitor and everything else.
|
||||
//
|
||||
// @group def_impl {
|
||||
template <class Helper, class LeafVisitor, class Visitor>
|
||||
template <class T, class Helper, class LeafVisitor, class Visitor>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
T*
|
||||
, char const* name
|
||||
, LeafVisitor
|
||||
, Helper const& helper
|
||||
, def_visitor<Visitor> const* v
|
||||
@@ -473,9 +482,10 @@ class class_ : public objects::class_base
|
||||
v->visit(*this, name, helper);
|
||||
}
|
||||
|
||||
template <class Fn, class Helper>
|
||||
template <class T, class Fn, class Helper>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
T*
|
||||
, char const* name
|
||||
, Fn fn
|
||||
, Helper const& helper
|
||||
, ...
|
||||
@@ -510,7 +520,7 @@ class class_ : public objects::class_base
|
||||
, Helper const& helper
|
||||
, mpl::bool_<true>)
|
||||
{
|
||||
detail::error::virtual_function_default<T,Fn>::must_be_derived_class_member(
|
||||
detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
|
||||
helper.default_implementation());
|
||||
|
||||
objects::add_to_namespace(
|
||||
@@ -554,7 +564,8 @@ class class_ : public objects::class_base
|
||||
, ...)
|
||||
{
|
||||
this->def_impl(
|
||||
name
|
||||
detail::unwrap_wrapper((W*)0)
|
||||
, name
|
||||
, fn
|
||||
, detail::def_helper<A1>(a1)
|
||||
, &fn
|
||||
@@ -569,23 +580,23 @@ class class_ : public objects::class_base
|
||||
// implementations
|
||||
//
|
||||
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline class_<T,X1,X2,X3>::class_(char const* name, char const* doc)
|
||||
template <class W, class X1, class X2, class X3>
|
||||
inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->initialize(init<>());
|
||||
// select_holder::assert_default_constructible();
|
||||
}
|
||||
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline class_<T,X1,X2,X3>::class_(char const* name, no_init_t)
|
||||
template <class W, class X1, class X2, class X3>
|
||||
inline class_<W,X1,X2,X3>::class_(char const* name, no_init_t)
|
||||
: base(name, id_vector::size, id_vector().ids)
|
||||
{
|
||||
this->initialize(no_init);
|
||||
}
|
||||
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline class_<T,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t)
|
||||
template <class W, class X1, class X2, class X3>
|
||||
inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->initialize(no_init);
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/registered_pointee.hpp>
|
||||
# include <boost/python/converter/object_manager.hpp>
|
||||
# include <boost/python/detail/void_ptr.hpp>
|
||||
# include <boost/python/detail/void_return.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/type_traits/has_trivial_copy.hpp>
|
||||
# include <boost/mpl/and.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
70
include/boost/python/detail/enable_if.hpp
Executable file
70
include/boost/python/detail/enable_if.hpp
Executable file
@@ -0,0 +1,70 @@
|
||||
// Copyright David Abrahams 2004. 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 ENABLE_IF_DWA2004722_HPP
|
||||
# define ENABLE_IF_DWA2004722_HPP
|
||||
|
||||
# include <boost/python/detail/sfinae.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
# include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <class C, class T = int>
|
||||
struct enable_if_arg
|
||||
{
|
||||
typedef typename mpl::if_<C,T,int&>::type type;
|
||||
};
|
||||
|
||||
template <class C, class T = int>
|
||||
struct disable_if_arg
|
||||
{
|
||||
typedef typename mpl::if_<C,int&,T>::type type;
|
||||
};
|
||||
|
||||
template <class C, class T>
|
||||
struct enable_if_ret
|
||||
{
|
||||
typedef typename mpl::if_<C,T,int[2]>::type type;
|
||||
};
|
||||
|
||||
template <class C, class T>
|
||||
struct disable_if_ret
|
||||
{
|
||||
typedef typename mpl::if_<C,int[2],T>::type type;
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
# elif !defined(BOOST_NO_SFINAE)
|
||||
# include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <class C, class T>
|
||||
struct enable_if_arg
|
||||
: enable_if<C,T>
|
||||
{};
|
||||
|
||||
template <class C, class T>
|
||||
struct disable_if_arg
|
||||
: disable_if<C,T>
|
||||
{};
|
||||
|
||||
template <class C, class T>
|
||||
struct enable_if_ret
|
||||
: enable_if<C,T>
|
||||
{};
|
||||
|
||||
template <class C, class T>
|
||||
struct disable_if_ret
|
||||
: disable_if<C,T>
|
||||
{};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
# endif
|
||||
|
||||
#endif // ENABLE_IF_DWA2004722_HPP
|
||||
29
include/boost/python/detail/is_wrapper.hpp
Executable file
29
include/boost/python/detail/is_wrapper.hpp
Executable file
@@ -0,0 +1,29 @@
|
||||
// Copyright David Abrahams 2004. 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 IS_WRAPPER_DWA2004723_HPP
|
||||
# define IS_WRAPPER_DWA2004723_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T> class wrapper;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&is_not_wrapper)[2];
|
||||
is_not_wrapper is_wrapper_helper(...);
|
||||
template <class T>
|
||||
char is_wrapper_helper(wrapper<T> const volatile*);
|
||||
|
||||
// A metafunction returning true iff T is [derived from] wrapper<U>
|
||||
template <class T>
|
||||
struct is_wrapper
|
||||
: mpl::bool_<(sizeof(detail::is_wrapper_helper((T*)0)) == 1)>
|
||||
{};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // IS_WRAPPER_DWA2004723_HPP
|
||||
13
include/boost/python/detail/sfinae.hpp
Executable file
13
include/boost/python/detail/sfinae.hpp
Executable file
@@ -0,0 +1,13 @@
|
||||
// Copyright David Abrahams 2004. 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 SFINAE_DWA2004723_HPP
|
||||
# define SFINAE_DWA2004723_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# if defined(BOOST_NO_SFINAE) && !defined(BOOST_MSVC)
|
||||
# define BOOST_PYTHON_NO_SFINAE
|
||||
# endif
|
||||
|
||||
#endif // SFINAE_DWA2004723_HPP
|
||||
@@ -1,150 +0,0 @@
|
||||
// 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 UNWIND_TYPE_DWA200222_HPP
|
||||
# define UNWIND_TYPE_DWA200222_HPP
|
||||
|
||||
# include <boost/python/detail/cv_category.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type_cv(U* p, cv_unqualified, Generator* = 0)
|
||||
{
|
||||
return Generator::execute(p);
|
||||
}
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type_cv(U const* p, const_, Generator* = 0)
|
||||
{
|
||||
return unwind_type(const_cast<U*>(p), (Generator*)0);
|
||||
}
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type_cv(U volatile* p, volatile_, Generator* = 0)
|
||||
{
|
||||
return unwind_type(const_cast<U*>(p), (Generator*)0);
|
||||
}
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type_cv(U const volatile* p, const_volatile_, Generator* = 0)
|
||||
{
|
||||
return unwind_type(const_cast<U*>(p), (Generator*)0);
|
||||
}
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_ptr_type(U* p, Generator* = 0)
|
||||
{
|
||||
typedef typename cv_category<U>::type tag;
|
||||
return unwind_type_cv<Generator>(p, tag());
|
||||
}
|
||||
|
||||
template <bool is_ptr>
|
||||
struct unwind_helper
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U p, Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type(p, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unwind_helper<false>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U& p, Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type(&p, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type(U const& p, Generator* = 0)
|
||||
{
|
||||
return unwind_helper<is_pointer<U>::value>::execute(p, (Generator*)0);
|
||||
}
|
||||
|
||||
enum { direct_ = 0, pointer_ = 1, reference_ = 2, reference_to_pointer_ = 3 };
|
||||
template <int indirection> struct unwind_helper2;
|
||||
|
||||
template <>
|
||||
struct unwind_helper2<direct_>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U(*)(), Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type((U*)0, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unwind_helper2<pointer_>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U*(*)(), Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type((U*)0, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unwind_helper2<reference_>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U&(*)(), Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type((U*)0, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unwind_helper2<reference_to_pointer_>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U&(*)(), Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type(U(0), (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
// Call this one with both template parameters explicitly specified
|
||||
// and no function arguments:
|
||||
//
|
||||
// return unwind_type<my_generator,T>();
|
||||
//
|
||||
// Doesn't work if T is an array type; we could handle that case, but
|
||||
// why bother?
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type(boost::type<U>*p = 0, Generator* = 0)
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(int, indirection
|
||||
= (is_pointer<U>::value ? pointer_ : 0)
|
||||
+ (is_reference_to_pointer<U>::value
|
||||
? reference_to_pointer_
|
||||
: is_reference<U>::value
|
||||
? reference_
|
||||
: 0));
|
||||
|
||||
return unwind_helper2<indirection>::execute((U(*)())0,(Generator*)0);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // UNWIND_TYPE_DWA200222_HPP
|
||||
31
include/boost/python/detail/unwrap_type_id.hpp
Executable file
31
include/boost/python/detail/unwrap_type_id.hpp
Executable file
@@ -0,0 +1,31 @@
|
||||
// Copyright David Abrahams 2004. 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 UNWRAP_TYPE_ID_DWA2004722_HPP
|
||||
# define UNWRAP_TYPE_ID_DWA2004722_HPP
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T> class wrapper;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
inline type_info unwrap_type_id(T*, ...)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
|
||||
template <class U, class T>
|
||||
inline type_info unwrap_type_id(U*, wrapper<T>*)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // UNWRAP_TYPE_ID_DWA2004722_HPP
|
||||
48
include/boost/python/detail/unwrap_wrapper.hpp
Executable file
48
include/boost/python/detail/unwrap_wrapper.hpp
Executable file
@@ -0,0 +1,48 @@
|
||||
// Copyright David Abrahams 2004. 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 UNWRAP_WRAPPER_DWA2004723_HPP
|
||||
# define UNWRAP_WRAPPER_DWA2004723_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/is_wrapper.hpp>
|
||||
# if defined(BOOST_PYTHON_NO_SFINAE)
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/identity.hpp>
|
||||
# else
|
||||
# include <boost/python/detail/enable_if.hpp>
|
||||
# endif
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
# if defined(BOOST_PYTHON_NO_SFINAE)
|
||||
template <class T>
|
||||
struct unwrap_wrapper_helper
|
||||
{
|
||||
typedef typename T::_wrapper_wrapped_type_ type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
typename mpl::apply_if<is_wrapper<T>,unwrap_wrapper_helper<T>,mpl::identity<T> >::type*
|
||||
unwrap_wrapper(T*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
# else
|
||||
template <class T>
|
||||
typename disable_if_ret<is_wrapper<T>,T*>::type
|
||||
unwrap_wrapper(T*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* unwrap_wrapper(wrapper<T>*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // UNWRAP_WRAPPER_DWA2004723_HPP
|
||||
86
include/boost/python/detail/wrapper_base.hpp
Executable file
86
include/boost/python/detail/wrapper_base.hpp
Executable file
@@ -0,0 +1,86 @@
|
||||
// Copyright David Abrahams 2004. 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 WRAPPER_BASE_DWA2004722_HPP
|
||||
# define WRAPPER_BASE_DWA2004722_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/type_traits/is_polymorphic.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
class override;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class BOOST_PYTHON_DECL wrapper_base;
|
||||
|
||||
namespace wrapper_base_ // ADL disabler
|
||||
{
|
||||
inline PyObject* get_owner(wrapper_base const volatile& w);
|
||||
|
||||
inline PyObject*
|
||||
owner_impl(void const volatile* x, mpl::false_)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline PyObject*
|
||||
owner_impl(T const volatile* x, mpl::true_)
|
||||
{
|
||||
if (wrapper_base const volatile* w = dynamic_cast<wrapper_base const volatile*>(x))
|
||||
{
|
||||
return wrapper_base_::get_owner(*w);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline PyObject*
|
||||
owner(T const volatile* x)
|
||||
{
|
||||
return wrapper_base_::owner_impl(x,is_polymorphic<T>());
|
||||
}
|
||||
}
|
||||
|
||||
class BOOST_PYTHON_DECL wrapper_base
|
||||
{
|
||||
friend void initialize_wrapper(PyObject* self, wrapper_base* w);
|
||||
friend PyObject* wrapper_base_::get_owner(wrapper_base const volatile& w);
|
||||
protected:
|
||||
wrapper_base() : m_self(0) {}
|
||||
|
||||
override get_override(
|
||||
char const* name, PyTypeObject* class_object) const;
|
||||
|
||||
private:
|
||||
void detach();
|
||||
|
||||
private:
|
||||
PyObject* m_self;
|
||||
};
|
||||
|
||||
namespace wrapper_base_ // ADL disabler
|
||||
{
|
||||
inline PyObject* get_owner(wrapper_base const volatile& w)
|
||||
{
|
||||
return w.m_self;
|
||||
}
|
||||
}
|
||||
|
||||
inline void initialize_wrapper(PyObject* self, wrapper_base* w)
|
||||
{
|
||||
w->m_self = self;
|
||||
}
|
||||
|
||||
inline void initialize_wrapper(PyObject* self, ...) {}
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // WRAPPER_BASE_DWA2004722_HPP
|
||||
@@ -12,16 +12,23 @@
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/registered_pointee.hpp>
|
||||
# include <boost/call_traits.hpp>
|
||||
|
||||
# include <boost/python/object_core.hpp>
|
||||
# include <boost/python/refcount.hpp>
|
||||
# include <boost/utility.hpp>
|
||||
|
||||
# include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
|
||||
# include <boost/python/detail/void_ptr.hpp>
|
||||
# include <boost/python/detail/void_return.hpp>
|
||||
# include <boost/utility.hpp>
|
||||
# include <boost/call_traits.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace api
|
||||
{
|
||||
class object;
|
||||
}
|
||||
|
||||
namespace converter
|
||||
{
|
||||
template <class Ptr>
|
||||
@@ -125,7 +132,7 @@ struct extract
|
||||
}
|
||||
|
||||
extract(PyObject*);
|
||||
extract(object const&);
|
||||
extract(api::object const&);
|
||||
};
|
||||
|
||||
//
|
||||
@@ -138,7 +145,7 @@ inline extract<T>::extract(PyObject* o)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline extract<T>::extract(object const& o)
|
||||
inline extract<T>::extract(api::object const& o)
|
||||
: base(o.ptr())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ struct register_base_of
|
||||
// need some registration of their own.
|
||||
//
|
||||
template <class T, class Bases>
|
||||
void register_shared_ptr_from_python_and_casts(T*, 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>());
|
||||
@@ -166,16 +166,13 @@ struct class_metadata
|
||||
use_value_holder
|
||||
, mpl::identity<held_type>
|
||||
, pointee<held_type>
|
||||
>::type wrapper;
|
||||
>::type wrapped;
|
||||
|
||||
// Determine whether wrapper needs to be separately registered
|
||||
typedef is_base_and_derived<T,wrapper> use_callback_class;
|
||||
|
||||
// Determine whether to use a holder with a back-reference
|
||||
// Determine whether to use a "back-reference holder"
|
||||
typedef mpl::or_<
|
||||
use_callback_class
|
||||
, has_back_reference<T>
|
||||
has_back_reference<T>
|
||||
, is_same<held_type_arg,T>
|
||||
, is_base_and_derived<T,wrapped>
|
||||
> use_back_reference;
|
||||
|
||||
// Select the holder.
|
||||
@@ -183,7 +180,7 @@ struct class_metadata
|
||||
use_back_reference
|
||||
, mpl::if_<
|
||||
use_value_holder
|
||||
, value_holder_back_reference<T, wrapper>
|
||||
, value_holder_back_reference<T, wrapped>
|
||||
, pointer_holder_back_reference<held_type,T>
|
||||
>
|
||||
, mpl::if_<
|
||||
@@ -195,52 +192,75 @@ struct class_metadata
|
||||
|
||||
inline static void register_() // Register the runtime metadata.
|
||||
{
|
||||
objects::register_shared_ptr_from_python_and_casts((T*)0, bases());
|
||||
|
||||
class_metadata::maybe_register_callback_class(use_callback_class());
|
||||
|
||||
class_metadata::maybe_register_class_to_python(is_noncopyable());
|
||||
|
||||
class_metadata::maybe_register_pointer_to_python(
|
||||
(use_value_holder*)0, (use_back_reference*)0);
|
||||
class_metadata::register_aux((T*)0);
|
||||
}
|
||||
|
||||
private:
|
||||
template <class T2>
|
||||
inline static void register_aux(python::wrapper<T2>*)
|
||||
{
|
||||
class_metadata::register_aux2((T2*)0, mpl::true_());
|
||||
}
|
||||
|
||||
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(void*,void*) {}
|
||||
|
||||
inline static void maybe_register_pointer_to_python(mpl::false_*, mpl::false_*)
|
||||
inline static void maybe_register_pointer_to_python(void*,void*,void*) {}
|
||||
|
||||
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<T, pointer_holder<held_type, T> >
|
||||
, make_ptr_instance<T2, pointer_holder<held_type, T2> >
|
||||
>()
|
||||
);
|
||||
}
|
||||
//
|
||||
// Support for registering to-python converters
|
||||
//
|
||||
inline static void maybe_register_class_to_python(mpl::true_) {}
|
||||
inline static void maybe_register_class_to_python(mpl::false_)
|
||||
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<T, make_instance<T, holder> >());
|
||||
python::detail::force_instantiate(class_cref_wrapper<T2, make_instance<T2, holder> >());
|
||||
}
|
||||
|
||||
//
|
||||
// Support for registering callback classes
|
||||
//
|
||||
inline static void maybe_register_callback_class(mpl::false_) {}
|
||||
inline static void maybe_register_callback_class(void*, mpl::false_) {}
|
||||
|
||||
inline static void maybe_register_callback_class(mpl::true_)
|
||||
template <class T2>
|
||||
inline static void maybe_register_callback_class(T2*, mpl::true_)
|
||||
{
|
||||
objects::register_shared_ptr_from_python_and_casts(
|
||||
(wrapper*)0, mpl::single_view<T>());
|
||||
(wrapped*)0, mpl::single_view<T2>());
|
||||
|
||||
// explicit qualification of type_id makes msvc6 happy
|
||||
objects::copy_class_object(python::type_id<T>(), python::type_id<wrapper>());
|
||||
objects::copy_class_object(python::type_id<T2>(), python::type_id<wrapped>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,13 +12,17 @@
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/python/instance_holder.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/object/inheritance_query.hpp>
|
||||
# include <boost/python/object/forward.hpp>
|
||||
|
||||
# include <boost/python/pointee.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
# include <boost/python/detail/wrapper_base.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
|
||||
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/apply.hpp>
|
||||
|
||||
@@ -31,6 +35,13 @@
|
||||
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T> class wrapper;
|
||||
|
||||
}}
|
||||
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
# if BOOST_WORKAROUND(__GNUC__, == 2)
|
||||
@@ -55,6 +66,17 @@ struct pointer_holder : instance_holder
|
||||
|
||||
private: // required holder implementation
|
||||
void* holds(type_info);
|
||||
|
||||
template <class T>
|
||||
inline void* holds_wrapped(type_info dst_t, wrapper<T>*,T* p)
|
||||
{
|
||||
return python::type_id<T>() == dst_t ? p : 0;
|
||||
}
|
||||
|
||||
inline void* holds_wrapped(type_info, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private: // data members
|
||||
Pointer m_p;
|
||||
@@ -107,6 +129,9 @@ void* pointer_holder<Pointer, Value>::holds(type_info dst_t)
|
||||
if (p == 0)
|
||||
return 0;
|
||||
|
||||
if (void* wrapped = holds_wrapped(dst_t, p, p))
|
||||
return wrapped;
|
||||
|
||||
type_info src_t = python::type_id<Value>();
|
||||
return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t);
|
||||
}
|
||||
@@ -145,11 +170,13 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t)
|
||||
# if (N != 0)
|
||||
template< BOOST_PP_ENUM_PARAMS_Z(1, N, class A) >
|
||||
# endif
|
||||
pointer_holder(PyObject* BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a))
|
||||
pointer_holder(PyObject* self BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a))
|
||||
: m_p(new Value(
|
||||
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
|
||||
))
|
||||
{}
|
||||
{
|
||||
python::detail::initialize_wrapper(self, &*this->m_p);
|
||||
}
|
||||
|
||||
# undef N
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
# include <boost/python/instance_holder.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/wrapper.hpp>
|
||||
|
||||
# include <boost/python/object/inheritance_query.hpp>
|
||||
# include <boost/python/object/forward.hpp>
|
||||
@@ -49,7 +50,17 @@ struct value_holder : instance_holder
|
||||
|
||||
private: // required holder implementation
|
||||
void* holds(type_info);
|
||||
|
||||
|
||||
template <class T>
|
||||
inline void* holds_wrapped(type_info dst_t, wrapper<T>*,T* p)
|
||||
{
|
||||
return python::type_id<T>() == dst_t ? p : 0;
|
||||
}
|
||||
|
||||
inline void* holds_wrapped(type_info, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
private: // data members
|
||||
Value m_held;
|
||||
};
|
||||
@@ -76,6 +87,9 @@ private: // required holder implementation
|
||||
template <class Value>
|
||||
void* value_holder<Value>::holds(type_info dst_t)
|
||||
{
|
||||
if (void* wrapped = holds_wrapped(dst_t, &m_held, &m_held))
|
||||
return wrapped;
|
||||
|
||||
type_info src_t = python::type_id<Value>();
|
||||
return src_t == dst_t ? &m_held
|
||||
: find_static_type(&m_held, src_t, dst_t);
|
||||
@@ -114,11 +128,13 @@ void* value_holder_back_reference<Value,Held>::holds(
|
||||
template <BOOST_PP_ENUM_PARAMS_Z(1, N, class A)>
|
||||
# endif
|
||||
value_holder(
|
||||
PyObject* BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a))
|
||||
PyObject* self BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a))
|
||||
: m_held(
|
||||
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
|
||||
)
|
||||
{}
|
||||
{
|
||||
python::detail::initialize_wrapper(self, &this->m_held);
|
||||
}
|
||||
|
||||
# undef N
|
||||
|
||||
|
||||
132
include/boost/python/override.hpp
Executable file
132
include/boost/python/override.hpp
Executable file
@@ -0,0 +1,132 @@
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
// Copyright David Abrahams 2004. 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 OVERRIDE_DWA2004721_HPP
|
||||
# define OVERRIDE_DWA2004721_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/converter/return_from_python.hpp>
|
||||
|
||||
# include <boost/python/extract.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/repeat.hpp>
|
||||
# include <boost/preprocessor/debug/line.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
class override;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class wrapper_base;
|
||||
|
||||
// The result of calling a method.
|
||||
class method_result
|
||||
{
|
||||
private:
|
||||
friend class override;
|
||||
explicit method_result(PyObject* x)
|
||||
: m_obj(x)
|
||||
{}
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
operator T()
|
||||
{
|
||||
converter::return_from_python<T> converter;
|
||||
return converter(m_obj.release());
|
||||
}
|
||||
|
||||
# if !defined(BOOST_MSVC) || BOOST_WORKAROUND(_MSC_FULL_VER, > 140040607)
|
||||
template <class T>
|
||||
operator T&() const
|
||||
{
|
||||
converter::return_from_python<T&> converter;
|
||||
return converter(m_obj.release());
|
||||
}
|
||||
# endif
|
||||
|
||||
template <class T>
|
||||
T as(type<T>* = 0)
|
||||
{
|
||||
converter::return_from_python<T> converter;
|
||||
return converter(m_obj.release());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T unchecked(type<T>* = 0)
|
||||
{
|
||||
return extract<T>(m_obj)();
|
||||
}
|
||||
private:
|
||||
mutable handle<> m_obj;
|
||||
};
|
||||
}
|
||||
|
||||
class override : public object
|
||||
{
|
||||
private:
|
||||
friend class detail::wrapper_base;
|
||||
override(handle<> x)
|
||||
: object(x)
|
||||
{}
|
||||
|
||||
public:
|
||||
detail::method_result
|
||||
operator()() const
|
||||
{
|
||||
detail::method_result x(
|
||||
PyEval_CallFunction(
|
||||
this->ptr()
|
||||
, const_cast<char*>("()")
|
||||
));
|
||||
return x;
|
||||
}
|
||||
|
||||
# define BOOST_PYTHON_fast_arg_to_python_get(z, n, _) \
|
||||
, converter::arg_to_python<A##n>(a##n).get()
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/override.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
# undef BOOST_PYTHON_fast_arg_to_python_get
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // OVERRIDE_DWA2004721_HPP
|
||||
|
||||
#else
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, override.hpp)
|
||||
# endif
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
template <
|
||||
BOOST_PP_ENUM_PARAMS_Z(1, N, class A)
|
||||
>
|
||||
detail::method_result
|
||||
operator()( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a) ) const
|
||||
{
|
||||
detail::method_result x(
|
||||
PyEval_CallFunction(
|
||||
this->ptr()
|
||||
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
|
||||
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_fast_arg_to_python_get, nil)
|
||||
));
|
||||
return x;
|
||||
}
|
||||
|
||||
# undef N
|
||||
#endif
|
||||
@@ -7,24 +7,58 @@
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
# include <boost/python/object/pointer_holder.hpp>
|
||||
# include <boost/python/object/instance.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/detail/unwind_type.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/shared_ptr.hpp>
|
||||
# include <boost/python/object/make_ptr_instance.hpp>
|
||||
# include <memory>
|
||||
|
||||
# include <boost/python/detail/none.hpp>
|
||||
|
||||
# include <boost/python/refcount.hpp>
|
||||
|
||||
# include <boost/type_traits/is_pointer.hpp>
|
||||
# include <boost/type_traits/is_polymorphic.hpp>
|
||||
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
# if defined(__ICL) && __ICL < 600
|
||||
# include <boost/shared_ptr.hpp>
|
||||
# else
|
||||
# include <memory>
|
||||
# endif
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T, class MakeHolder>
|
||||
struct to_python_indirect
|
||||
{
|
||||
PyObject* operator()(T ptr) const;
|
||||
template <class U>
|
||||
inline PyObject*
|
||||
operator()(U const& ref) const
|
||||
{
|
||||
return this->execute(const_cast<U&>(ref), is_pointer<U>());
|
||||
}
|
||||
|
||||
private:
|
||||
static PyTypeObject* type();
|
||||
template <class U>
|
||||
inline PyObject* execute(U* ptr, mpl::true_) const
|
||||
{
|
||||
// No special NULL treatment for references
|
||||
if (ptr == 0)
|
||||
return python::detail::none();
|
||||
else
|
||||
return this->execute(*ptr, mpl::false_());
|
||||
}
|
||||
|
||||
template <class U>
|
||||
inline PyObject* execute(U const& x, mpl::false_) const
|
||||
{
|
||||
U* const p = &const_cast<U&>(x);
|
||||
if (is_polymorphic<U>::value)
|
||||
{
|
||||
if (PyObject* o = detail::wrapper_base_::owner(p))
|
||||
return incref(o);
|
||||
}
|
||||
return MakeHolder::execute(p);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
@@ -34,9 +68,8 @@ namespace detail
|
||||
{
|
||||
struct make_owning_holder
|
||||
{
|
||||
typedef PyObject* result_type;
|
||||
template <class T>
|
||||
static result_type execute(T* p)
|
||||
static PyObject* execute(T* p)
|
||||
{
|
||||
// can't use auto_ptr with Intel 5 and VC6 Dinkum library
|
||||
// for some reason. We get link errors against the auto_ptr
|
||||
@@ -48,66 +81,21 @@ namespace detail
|
||||
# endif
|
||||
typedef objects::pointer_holder<smart_pointer, T> holder_t;
|
||||
|
||||
smart_pointer ptr(p);
|
||||
smart_pointer ptr(const_cast<T*>(p));
|
||||
return objects::make_ptr_instance<T, holder_t>::execute(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
struct make_reference_holder
|
||||
{
|
||||
typedef PyObject* result_type;
|
||||
template <class T>
|
||||
static result_type execute(T* p)
|
||||
static PyObject* execute(T* p)
|
||||
{
|
||||
typedef objects::pointer_holder<T*, T> holder_t;
|
||||
return objects::make_ptr_instance<T, holder_t>::execute(p);
|
||||
T* q = const_cast<T*>(p);
|
||||
return objects::make_ptr_instance<T, holder_t>::execute(q);
|
||||
}
|
||||
};
|
||||
|
||||
struct get_pointer_class
|
||||
{
|
||||
typedef PyTypeObject* result_type;
|
||||
template <class T>
|
||||
static result_type execute(T* p)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(is_class<T>::value);
|
||||
return converter::registered<T>::converters.class_object;
|
||||
}
|
||||
};
|
||||
|
||||
// null_pointer_to_none -- return none() for null pointers and 0 for all other types/values
|
||||
//
|
||||
// Uses simulated partial ordering
|
||||
template <class T>
|
||||
inline PyObject* null_pointer_to_none(T&, int)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// overload for pointers
|
||||
template <class T>
|
||||
inline PyObject* null_pointer_to_none(T* x, long)
|
||||
{
|
||||
return x == 0 ? python::detail::none() : 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class MakeHolder>
|
||||
inline PyObject* to_python_indirect<T,MakeHolder>::operator()(T x) const
|
||||
{
|
||||
BOOST_STATIC_ASSERT(is_pointer<T>::value || is_reference<T>::value);
|
||||
|
||||
PyObject* const null_result = detail::null_pointer_to_none(x, 1L);
|
||||
if (null_result != 0)
|
||||
return null_result;
|
||||
|
||||
return detail::unwind_type<MakeHolder>(x);
|
||||
}
|
||||
|
||||
template <class T, class MakeHolder>
|
||||
inline PyTypeObject* to_python_indirect<T,MakeHolder>::type()
|
||||
{
|
||||
return detail::unwind_type<detail::get_pointer_class,T>();
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
30
include/boost/python/wrapper.hpp
Executable file
30
include/boost/python/wrapper.hpp
Executable file
@@ -0,0 +1,30 @@
|
||||
// Copyright David Abrahams 2004. 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 WRAPPER_DWA2004720_HPP
|
||||
# define WRAPPER_DWA2004720_HPP
|
||||
|
||||
# include <boost/python/detail/wrapper_base.hpp>
|
||||
# include <boost/python/override.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/detail/sfinae.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
class wrapper : public detail::wrapper_base
|
||||
{
|
||||
# if defined(BOOST_PYTHON_NO_SFINAE)
|
||||
typedef T _wrapper_wrapped_type_;
|
||||
# endif
|
||||
protected:
|
||||
override get_override(char const* name) const
|
||||
{
|
||||
return this->wrapper_base::get_override(
|
||||
name, converter::registered<T>::converters.get_class_object());
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // WRAPPER_DWA2004720_HPP
|
||||
@@ -80,7 +80,7 @@ PyTypeObject life_support_type = {
|
||||
|
||||
PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient)
|
||||
{
|
||||
if (nurse == Py_None)
|
||||
if (nurse == Py_None || nurse == patient)
|
||||
return nurse;
|
||||
|
||||
if (life_support_type.ob_type == 0)
|
||||
|
||||
65
src/wrapper.cpp
Executable file
65
src/wrapper.cpp
Executable file
@@ -0,0 +1,65 @@
|
||||
// Copyright David Abrahams 2004. 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)
|
||||
|
||||
#include <boost/python/wrapper.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
override wrapper_base::get_override(
|
||||
char const* name
|
||||
, PyTypeObject* class_object
|
||||
) const
|
||||
{
|
||||
if (this->m_self)
|
||||
{
|
||||
if (handle<> m = handle<>(
|
||||
python::allow_null(
|
||||
::PyObject_GetAttrString(
|
||||
this->m_self, const_cast<char*>(name))))
|
||||
)
|
||||
{
|
||||
PyObject* borrowed_f = 0;
|
||||
|
||||
if (
|
||||
PyMethod_Check(m.get())
|
||||
&& ((PyMethodObject*)m.get())->im_self == this->m_self
|
||||
&& class_object->tp_dict != 0
|
||||
)
|
||||
{
|
||||
borrowed_f = ::PyDict_GetItemString(class_object->tp_dict, name);
|
||||
|
||||
|
||||
}
|
||||
if (borrowed_f != ((PyMethodObject*)m.get())->im_func)
|
||||
return override(m);
|
||||
}
|
||||
}
|
||||
return override(handle<>(detail::none()));
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
namespace converter
|
||||
{
|
||||
PyObject* BOOST_PYTHON_DECL do_polymorphic_ref_to_python(
|
||||
python::detail::wrapper_base const volatile* x, type_info src
|
||||
)
|
||||
{
|
||||
if (x == 0)
|
||||
{
|
||||
::PyErr_Format(
|
||||
PyExc_TypeError
|
||||
, "Attempting to returning pointer or reference to instance of %s\n"
|
||||
"for which no corresponding Python object exists. Wrap this function"
|
||||
"with a return return value policy"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}} // namespace boost::python::detail
|
||||
@@ -99,6 +99,7 @@ bpl-test crossmod_exception
|
||||
[ bpl-test staticmethod ]
|
||||
[ bpl-test shared_ptr ]
|
||||
[ bpl-test polymorphism ]
|
||||
[ bpl-test polymorphism2 ]
|
||||
[ bpl-test auto_ptr ]
|
||||
[ bpl-test minimal ]
|
||||
[ bpl-test args ]
|
||||
|
||||
@@ -74,7 +74,7 @@ void test()
|
||||
)();
|
||||
|
||||
// Retrieve the main module's namespace
|
||||
python::object main_namespace(main_module.attr("__dict__"));
|
||||
python::object main_namespace((main_module.attr("__dict__")));
|
||||
|
||||
// Define the derived class in Python.
|
||||
// (You'll normally want to put this in a .py file.)
|
||||
@@ -115,12 +115,12 @@ test_tutorial()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
||||
object main_module(
|
||||
handle<>(borrowed(PyImport_AddModule("__main__"))));
|
||||
object main_module((
|
||||
handle<>(borrowed(PyImport_AddModule("__main__")))));
|
||||
|
||||
object main_namespace = main_module.attr("__dict__");
|
||||
|
||||
handle<>(PyRun_String(
|
||||
handle<> ignored((PyRun_String(
|
||||
|
||||
"hello = file('hello.txt', 'w')\n"
|
||||
"hello.write('Hello world!')\n"
|
||||
@@ -129,7 +129,7 @@ test_tutorial()
|
||||
, Py_file_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr())
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -137,29 +137,29 @@ test_tutorial2()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
||||
object main_module(
|
||||
handle<>(borrowed(PyImport_AddModule("__main__"))));
|
||||
object main_module((
|
||||
handle<>(borrowed(PyImport_AddModule("__main__")))));
|
||||
|
||||
object main_namespace = main_module.attr("__dict__");
|
||||
|
||||
handle<>(PyRun_String(
|
||||
handle<> ignored((PyRun_String(
|
||||
|
||||
"result = 5 ** 2"
|
||||
|
||||
, Py_file_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr())
|
||||
);
|
||||
));
|
||||
|
||||
int five_squared = extract<int>(main_namespace["result"]);
|
||||
assert(five_squared == 25);
|
||||
|
||||
object result(handle<>(
|
||||
object result((handle<>(
|
||||
PyRun_String("5 ** 2"
|
||||
, Py_eval_input
|
||||
, main_namespace.ptr()
|
||||
, main_namespace.ptr()))
|
||||
);
|
||||
));
|
||||
|
||||
int five_squared2 = extract<int>(result);
|
||||
assert(five_squared2 == 25);
|
||||
|
||||
159
test/polymorphism2.cpp
Executable file
159
test/polymorphism2.cpp
Executable file
@@ -0,0 +1,159 @@
|
||||
// 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/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/return_value_policy.hpp>
|
||||
#include <boost/python/manage_new_object.hpp>
|
||||
#include <boost/python/reference_existing_object.hpp>
|
||||
#include <boost/python/pure_virtual.hpp>
|
||||
#include <boost/python/wrapper.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/call.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct P
|
||||
{
|
||||
virtual ~P(){}
|
||||
virtual char const* f() = 0;
|
||||
char const* g() { return "P::g()"; }
|
||||
};
|
||||
|
||||
struct PCallback : P, wrapper<P>
|
||||
{
|
||||
char const* f()
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
return call<char const*>(this->get_override("f").ptr());
|
||||
#else
|
||||
return this->get_override("f")();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
struct Q : virtual P
|
||||
{
|
||||
char const* f() { return "Q::f()"; }
|
||||
};
|
||||
|
||||
struct A
|
||||
{
|
||||
virtual ~A(){}
|
||||
virtual char const* f() { return "A::f()"; }
|
||||
};
|
||||
|
||||
struct ACallback : A, wrapper<A>
|
||||
{
|
||||
char const* f()
|
||||
{
|
||||
if (override f = this->get_override("f"))
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
return call<char const*>(f.ptr());
|
||||
#else
|
||||
return f();
|
||||
#endif
|
||||
else
|
||||
return A::f();
|
||||
}
|
||||
};
|
||||
|
||||
struct B : A
|
||||
{
|
||||
virtual char const* f() { return "B::f()"; }
|
||||
};
|
||||
|
||||
struct C : A
|
||||
{
|
||||
virtual char const* f() { return "C::f()"; }
|
||||
};
|
||||
|
||||
struct D : A
|
||||
{
|
||||
virtual char const* f() { return "D::f()"; }
|
||||
char const* g() { return "D::g()"; }
|
||||
};
|
||||
|
||||
struct DCallback : D, wrapper<D>
|
||||
{
|
||||
char const* f()
|
||||
{
|
||||
if (override f = this->get_override("f"))
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
return call<char const*>(f.ptr());
|
||||
#else
|
||||
return f();
|
||||
#endif
|
||||
else
|
||||
return D::f();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
A& getBCppObj ()
|
||||
{
|
||||
static B b;
|
||||
return b;
|
||||
}
|
||||
|
||||
char const* call_f(A& a) { return a.f(); }
|
||||
|
||||
A* factory(unsigned choice)
|
||||
{
|
||||
switch (choice % 3)
|
||||
{
|
||||
case 0: return new A;
|
||||
break;
|
||||
case 1: return new B;
|
||||
break;
|
||||
default: return new C;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
C& getCCppObj ()
|
||||
{
|
||||
static C c;
|
||||
return c;
|
||||
}
|
||||
|
||||
A* pass_a(A* x) { return x; }
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(polymorphism2_ext)
|
||||
{
|
||||
class_<ACallback,boost::noncopyable>("A")
|
||||
.def("f", &A::f)
|
||||
;
|
||||
|
||||
def("getBCppObj", getBCppObj, return_value_policy<reference_existing_object>());
|
||||
|
||||
class_<C,bases<A>,boost::noncopyable>("C")
|
||||
.def("f", &C::f)
|
||||
;
|
||||
|
||||
class_<DCallback,bases<A>,boost::noncopyable>("D")
|
||||
.def("f", &D::f)
|
||||
.def("g", &D::g)
|
||||
;
|
||||
|
||||
def("pass_a", &pass_a, return_internal_reference<>());
|
||||
|
||||
def("getCCppObj", getCCppObj, return_value_policy<reference_existing_object>());
|
||||
|
||||
def("factory", factory, return_value_policy<manage_new_object>());
|
||||
|
||||
def("call_f", call_f);
|
||||
|
||||
class_<PCallback,boost::noncopyable>("P")
|
||||
.def("f", pure_virtual(&P::f))
|
||||
;
|
||||
|
||||
class_<Q, bases<P> >("Q")
|
||||
.def("g", &P::g) // make sure virtual inheritance doesn't interfere
|
||||
;
|
||||
}
|
||||
|
||||
//#include "module_tail.cpp"
|
||||
71
test/polymorphism2.py
Normal file
71
test/polymorphism2.py
Normal file
@@ -0,0 +1,71 @@
|
||||
import unittest
|
||||
from polymorphism2_ext import *
|
||||
|
||||
class PolymorphTest(unittest.TestCase):
|
||||
|
||||
def testReturnCpp(self):
|
||||
|
||||
# Python Created Object With Same Id As
|
||||
# Cpp Created B Object
|
||||
# b = B(872)
|
||||
|
||||
# Get Reference To Cpp Created B Object
|
||||
a = getBCppObj()
|
||||
|
||||
# Python Created B Object and Cpp B Object
|
||||
# Should have same result by calling f()
|
||||
self.failUnlessEqual ('B::f()', a.f())
|
||||
self.failUnlessEqual ('B::f()', call_f(a))
|
||||
self.failUnlessEqual ('A::f()', call_f(A()))
|
||||
|
||||
def test_references(self):
|
||||
# B is not exposed to Python
|
||||
a = getBCppObj()
|
||||
self.failUnlessEqual(type(a), A)
|
||||
|
||||
# C is exposed to Python
|
||||
c = getCCppObj()
|
||||
self.failUnlessEqual(type(c), C)
|
||||
|
||||
def test_factory(self):
|
||||
self.failUnlessEqual(type(factory(0)), A)
|
||||
self.failUnlessEqual(type(factory(1)), A)
|
||||
self.failUnlessEqual(type(factory(2)), C)
|
||||
|
||||
def test_return_py(self):
|
||||
|
||||
class X(A):
|
||||
def f(self):
|
||||
return 'X.f'
|
||||
|
||||
x = X()
|
||||
|
||||
self.failUnlessEqual ('X.f', x.f())
|
||||
self.failUnlessEqual ('X.f', call_f(x))
|
||||
|
||||
def test_wrapper_downcast(self):
|
||||
a = pass_a(D())
|
||||
self.failUnlessEqual('D::g()', a.g())
|
||||
|
||||
def test_pure_virtual(self):
|
||||
p = P()
|
||||
self.assertRaises(RuntimeError, p.f)
|
||||
|
||||
q = Q()
|
||||
self.failUnlessEqual ('Q::f()', q.f())
|
||||
|
||||
class R(P):
|
||||
def f(self):
|
||||
return 'R.f'
|
||||
|
||||
r = R()
|
||||
self.failUnlessEqual ('R.f', r.f())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# remove the option which upsets unittest
|
||||
import sys
|
||||
sys.argv = [ x for x in sys.argv if x != '--broken-auto-ptr' ]
|
||||
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user