mirror of
https://github.com/boostorg/python.git
synced 2026-01-26 06:42:27 +00:00
Finally fixed polymorphism issues
[SVN r16435]
This commit is contained in:
@@ -8,37 +8,43 @@
|
||||
|
||||
# include <boost/python/class_fwd.hpp>
|
||||
# include <boost/python/object/class.hpp>
|
||||
|
||||
# include <boost/python/bases.hpp>
|
||||
|
||||
# include <boost/python/object.hpp>
|
||||
|
||||
# include <boost/python/type_id.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/mpl/bool_c.hpp>
|
||||
# include <boost/python/object/select_holder.hpp>
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/python/object/make_instance.hpp>
|
||||
# include <boost/python/data_members.hpp>
|
||||
# include <boost/utility.hpp>
|
||||
# include <boost/python/object/pickle_support.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
# include <boost/python/object/add_to_namespace.hpp>
|
||||
# include <boost/python/signature.hpp>
|
||||
# include <boost/python/init.hpp>
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
|
||||
# include <boost/python/detail/string_literal.hpp>
|
||||
# include <boost/type_traits/ice.hpp>
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
# include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
# include <boost/type_traits/is_polymorphic.hpp>
|
||||
|
||||
# include <boost/mpl/size.hpp>
|
||||
# include <boost/mpl/for_each.hpp>
|
||||
# include <boost/mpl/bool_c.hpp>
|
||||
# include <boost/mpl/logical/not.hpp>
|
||||
|
||||
# include <boost/python/object/select_holder.hpp>
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/python/object/make_instance.hpp>
|
||||
# include <boost/python/object/pickle_support.hpp>
|
||||
# include <boost/python/object/add_to_namespace.hpp>
|
||||
# include <boost/python/object/class_converters.hpp>
|
||||
|
||||
# include <boost/python/detail/string_literal.hpp>
|
||||
# include <boost/python/detail/overloads_fwd.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/member_function_cast.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
|
||||
# include <boost/utility.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
enum no_init_t { no_init };
|
||||
@@ -89,6 +95,54 @@ namespace detail
|
||||
{
|
||||
SelectHolder::register_();
|
||||
}
|
||||
|
||||
namespace error
|
||||
{
|
||||
//
|
||||
// A meta-assertion mechanism which prints nice error messages and
|
||||
// backtraces on lots of compilers. Usage:
|
||||
//
|
||||
// assertion<C>::failed
|
||||
//
|
||||
// where C is an MPL metafunction class
|
||||
//
|
||||
|
||||
template <class C> struct assertion_failed { };
|
||||
template <class C> struct assertion_ok { typedef C failed; };
|
||||
|
||||
template <class C>
|
||||
struct assertion
|
||||
: mpl::if_<C, assertion_ok<C>, assertion_failed<C> >::type
|
||||
{};
|
||||
|
||||
//
|
||||
// Checks for validity of arguments used to define virtual
|
||||
// functions with default implementations.
|
||||
//
|
||||
|
||||
template <class Default>
|
||||
void not_a_derived_class_member(Default) {}
|
||||
|
||||
template <class T, class Fn>
|
||||
struct virtual_function_default
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
: assertion<is_polymorphic<T> >::failed
|
||||
, assertion<is_member_function_pointer<Fn> >::failed
|
||||
# endif
|
||||
{
|
||||
template <class Default>
|
||||
static void
|
||||
must_be_derived_class_member(Default const&)
|
||||
{
|
||||
typedef typename assertion<mpl::logical_not<is_same<Default,Fn> > >::failed test0;
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename assertion<is_polymorphic<T> >::failed test1;
|
||||
typedef typename assertion<is_member_function_pointer<Fn> >::failed test2;
|
||||
# endif
|
||||
not_a_derived_class_member<Default>(Fn());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// This is the primary mechanism through which users will expose
|
||||
@@ -313,22 +367,6 @@ class class_ : public objects::class_base
|
||||
// things which are already wrapped into callable python::object
|
||||
// instances and everything else.
|
||||
//
|
||||
template <class Fn, class Helper>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
, Fn fn
|
||||
, Helper const& helper
|
||||
, ...)
|
||||
{
|
||||
objects::add_to_namespace(
|
||||
*this, name,
|
||||
make_function(
|
||||
// This bit of nastiness casts F to a member function of T if possible.
|
||||
detail::member_function_cast<T,Fn>::stage1(fn).stage2((T*)0).stage3(fn)
|
||||
, helper.policies(), helper.keywords())
|
||||
, helper.doc());
|
||||
}
|
||||
|
||||
template <class F, class A1>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
@@ -345,6 +383,50 @@ class class_ : public objects::class_base
|
||||
objects::add_to_namespace(*this, name, f, helper.doc());
|
||||
}
|
||||
|
||||
template <class Fn, class Helper>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
, Fn fn
|
||||
, Helper const& helper
|
||||
, ...)
|
||||
{
|
||||
objects::add_to_namespace(
|
||||
*this, name,
|
||||
make_function(
|
||||
// This bit of nastiness casts F to a member function of T if possible.
|
||||
detail::member_function_cast<T,Fn>::stage1(fn).stage2((T*)0).stage3(fn)
|
||||
, helper.policies(), helper.keywords())
|
||||
, helper.doc());
|
||||
|
||||
this->def_default(name, fn, helper, mpl::bool_c<Helper::has_default_implementation>());
|
||||
}
|
||||
|
||||
//
|
||||
// These two overloads handle the definition of default
|
||||
// implementation overloads for virtual functions. The second one
|
||||
// handles the case where no default implementation was specified.
|
||||
//
|
||||
template <class Fn, class Helper>
|
||||
inline void def_default(
|
||||
char const* name
|
||||
, Fn fn
|
||||
, Helper const& helper
|
||||
, mpl::bool_c<true>)
|
||||
{
|
||||
detail::error::virtual_function_default<T,Fn>::must_be_derived_class_member(
|
||||
helper.default_implementation());
|
||||
|
||||
objects::add_to_namespace(
|
||||
*this, name,
|
||||
make_function(
|
||||
helper.default_implementation(), helper.policies(), helper.keywords())
|
||||
);
|
||||
}
|
||||
|
||||
template <class Fn, class Helper>
|
||||
inline void def_default(char const*, Fn, Helper const&, mpl::bool_c<false>)
|
||||
{ }
|
||||
|
||||
//
|
||||
// These two overloads discriminate between def() as applied to
|
||||
// regular functions and def() as applied to the result of
|
||||
|
||||
@@ -56,7 +56,7 @@ struct select_result_converter
|
||||
};
|
||||
|
||||
|
||||
template <unsigned> struct caller_gen;
|
||||
template <unsigned> struct caller_arity;
|
||||
|
||||
# define BOOST_PYTHON_NEXT(init,name,n) \
|
||||
typedef BOOST_PP_IF(n,typename BOOST_PP_CAT(name,BOOST_PP_DEC(n)) ::next, init) name##n;
|
||||
@@ -81,8 +81,8 @@ template <unsigned> struct caller_gen;
|
||||
template <class F, class ConverterGenerators, class CallPolicies, class Sig>
|
||||
struct caller_base_select
|
||||
{
|
||||
enum { n_arguments = mpl::size<Sig>::value - 1 };
|
||||
typedef typename caller_gen<n_arguments>::template impl<F,ConverterGenerators,CallPolicies,Sig> type;
|
||||
enum { arity = mpl::size<Sig>::value - 1 };
|
||||
typedef typename caller_arity<arity>::template impl<F,ConverterGenerators,CallPolicies,Sig> type;
|
||||
};
|
||||
|
||||
// A function object type which wraps C++ objects as Python callable
|
||||
@@ -131,7 +131,7 @@ struct caller
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
template <>
|
||||
struct caller_gen<N>
|
||||
struct caller_arity<N>
|
||||
{
|
||||
template <class F, class ConverterGenerators, class Policies, class Sig>
|
||||
struct impl
|
||||
|
||||
@@ -97,12 +97,11 @@ namespace detail
|
||||
template <class Tuple>
|
||||
struct doc_extract
|
||||
: tuple_extract<
|
||||
Tuple,
|
||||
mpl::logical_not<
|
||||
Tuple
|
||||
, mpl::logical_not<
|
||||
mpl::logical_or<
|
||||
is_reference_to_class<mpl::_1>
|
||||
, is_reference_to_function_pointer<mpl::_1 >
|
||||
, is_reference_to_function<mpl::_1 >
|
||||
, is_reference_to_member_function_pointer<mpl::_1 >
|
||||
>
|
||||
>
|
||||
>
|
||||
@@ -118,8 +117,8 @@ namespace detail
|
||||
template <class Tuple>
|
||||
struct policy_extract
|
||||
: tuple_extract<
|
||||
Tuple,
|
||||
mpl::logical_and<
|
||||
Tuple
|
||||
, mpl::logical_and<
|
||||
mpl::logical_not<is_same<not_specified const&,mpl::_1> >
|
||||
, is_reference_to_class<mpl::_1 >
|
||||
, mpl::logical_not<is_reference_to_keywords<mpl::_1 > >
|
||||
@@ -131,12 +130,9 @@ namespace detail
|
||||
template <class Tuple>
|
||||
struct default_implementation_extract
|
||||
: tuple_extract<
|
||||
Tuple,
|
||||
mpl::logical_or<
|
||||
is_reference_to_function_pointer<mpl::_1 >
|
||||
, is_reference_to_function<mpl::_1 >
|
||||
Tuple
|
||||
, is_reference_to_member_function_pointer<mpl::_1 >
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
@@ -161,8 +157,8 @@ namespace detail
|
||||
, default_call_policies
|
||||
, keywords<0>
|
||||
, char const*
|
||||
, void(*)() // A function pointer type which is never an
|
||||
// appropriate default implementation
|
||||
, void(not_specified::*)() // A function pointer type which is never an
|
||||
// appropriate default implementation
|
||||
> all_t;
|
||||
|
||||
// Constructors; these initialize an member of the tuple type
|
||||
@@ -172,15 +168,16 @@ namespace detail
|
||||
def_helper(T1 const& a1, T2 const& a2, T3 const& a3) : m_all(a1,a2,a3,m_nil) {}
|
||||
def_helper(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4) : m_all(a1,a2,a3,a4) {}
|
||||
|
||||
private: // type
|
||||
private: // types
|
||||
typedef typename default_implementation_extract<all_t>::result_type default_implementation_t;
|
||||
|
||||
public: // Constants which can be used for static assertions.
|
||||
|
||||
public: // Constant which can be used for static assertions. Users
|
||||
// must not supply a default implementation for non-class
|
||||
// methods.
|
||||
// Users must not supply a default implementation for non-class
|
||||
// methods.
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, has_default_implementation = (
|
||||
!is_same<default_implementation_t, void(*)()>::value));
|
||||
!is_same<default_implementation_t, void(not_specified::*)()>::value));
|
||||
|
||||
public: // Extractor functions which pull the appropriate value out
|
||||
// of the tuple
|
||||
@@ -201,7 +198,7 @@ namespace detail
|
||||
|
||||
default_implementation_t default_implementation() const
|
||||
{
|
||||
return policy_extract<all_t>::extract(m_all);
|
||||
return default_implementation_extract<all_t>::extract(m_all);
|
||||
}
|
||||
|
||||
private: // data members
|
||||
|
||||
@@ -302,8 +302,7 @@ typename is_const_help<V>::type reference_to_const_helper(V&);
|
||||
outer_no_type
|
||||
reference_to_const_helper(...);
|
||||
|
||||
template <bool ref = true>
|
||||
struct is_reference_to_const_helper1
|
||||
struct true_helper1
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
@@ -315,6 +314,21 @@ struct is_reference_to_const_helper1
|
||||
};
|
||||
};
|
||||
|
||||
template <bool ref = true>
|
||||
struct is_reference_to_const_helper1 : true_helper1
|
||||
{
|
||||
# if 0
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
static T t;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value
|
||||
= sizeof(reference_to_const_helper(t)) == sizeof(inner_yes_type));
|
||||
};
|
||||
# endif
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_reference_to_const_helper1<false> : false_helper1
|
||||
{
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/detail/this_arg_from_python.hpp>
|
||||
|
||||
# include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
|
||||
@@ -52,7 +51,6 @@ template <class T> struct is_defaulted_virtual_fn;
|
||||
// Tag types describing invocation methods
|
||||
struct fn_tag {};
|
||||
struct mem_fn_tag {};
|
||||
struct virtual_fn_tag {};
|
||||
|
||||
// A metafunction returning the appropriate tag type for invoking an
|
||||
// object of type T.
|
||||
@@ -61,11 +59,7 @@ struct invoke_tag
|
||||
: mpl::if_<
|
||||
is_member_function_pointer<T>
|
||||
, mem_fn_tag
|
||||
, typename mpl::if_<
|
||||
is_defaulted_virtual_fn<T>
|
||||
, virtual_fn_tag
|
||||
, fn_tag
|
||||
>::type
|
||||
, fn_tag
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -106,25 +100,6 @@ inline PyObject* invoke(mem_fn_tag, void_result_to_python, F& f, TC& tc BOOST_PP
|
||||
return none();
|
||||
}
|
||||
|
||||
template <class RC, class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
|
||||
inline PyObject* invoke(virtual_fn_tag, RC*, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
{
|
||||
return RC()(
|
||||
tc.use_default()
|
||||
? f.default_impl(tc() BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT))
|
||||
: (tc().*f.dispatch)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT)) );
|
||||
}
|
||||
|
||||
template <class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
|
||||
inline PyObject* invoke(virtual_fn_tag, void_result_to_python, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
|
||||
{
|
||||
if (tc.use_default())
|
||||
f.default_impl(tc() BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, ac,()BOOST_PP_INTERCEPT));
|
||||
else
|
||||
(tc().*f.dispatch)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac,()BOOST_PP_INTERCEPT));
|
||||
return none();
|
||||
}
|
||||
|
||||
# undef N
|
||||
|
||||
#endif // BOOST_PP_IS_ITERATING
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#error obsolete
|
||||
// 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
|
||||
@@ -7,6 +8,7 @@
|
||||
# define THIS_ARG_FROM_PYTHON_DWA20021122_HPP
|
||||
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
# include <boost/python/back_reference.hpp>
|
||||
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
|
||||
@@ -14,75 +16,79 @@
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <class T, class Wrap = not_specified>
|
||||
struct this_ptr_arg_from_python : converter::arg_lvalue_from_python_base
|
||||
{
|
||||
this_ptr_arg_from_python(PyObject* x)
|
||||
: converter::arg_lvalue_from_python_base(
|
||||
converter::get_lvalue_from_python(x, converter::registered<T>::converters))
|
||||
{}
|
||||
template <class T, class Wrap = not_specified>
|
||||
struct this_ptr_arg_from_python : converter::arg_lvalue_from_python_base
|
||||
{
|
||||
this_ptr_arg_from_python(PyObject* x)
|
||||
: converter::arg_lvalue_from_python_base(
|
||||
converter::get_lvalue_from_python(x, converter::registered<T>::converters))
|
||||
{}
|
||||
|
||||
typedef T* result_type;
|
||||
T* operator()() const
|
||||
{
|
||||
return static_cast<T*>(this->result());
|
||||
}
|
||||
|
||||
bool use_default() const
|
||||
{
|
||||
return dynamic_cast<Wrap*>((*this)());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Wrap = not_specified>
|
||||
struct this_ref_arg_from_python : this_ptr_arg_from_python<T,Wrap>
|
||||
{
|
||||
typedef this_ptr_arg_from_python<T,Wrap> base;
|
||||
this_ref_arg_from_python(PyObject* x) : base(x) {}
|
||||
typedef T& result_type;
|
||||
|
||||
result_type operator()() const
|
||||
{
|
||||
return *this->base::operator()();
|
||||
}
|
||||
};
|
||||
typedef T* result_type;
|
||||
T* operator()() const
|
||||
{
|
||||
return static_cast<T*>(this->result());
|
||||
}
|
||||
|
||||
// An MPL metafunction class which returns a `this' converter
|
||||
// appropriate for ArgType, where the target of the member function is
|
||||
// a class of type T.
|
||||
template <class T, class Wrap = not_specified>
|
||||
struct gen_this_from_python
|
||||
{
|
||||
// Note: there will almost always be an compile-time error if the
|
||||
// argument type is neither a reference nor a pointer, since T*
|
||||
// will be extracted in that case and passed on to the wrapped
|
||||
// function.
|
||||
template <class ArgType> struct apply
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, use_ptr
|
||||
= is_pointer<ArgType>::value
|
||||
|| boost::python::detail::is_reference_to_pointer<ArgType>::value
|
||||
&& boost::python::detail::is_reference_to_const<ArgType>::value
|
||||
&& !boost::python::detail::is_reference_to_volatile<ArgType>::value);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
use_ptr
|
||||
, this_ptr_arg_from_python<T,Wrap>
|
||||
, this_ref_arg_from_python<T,Wrap>
|
||||
>::type type;
|
||||
};
|
||||
};
|
||||
bool use_default() const
|
||||
{
|
||||
return dynamic_cast<Wrap*>((*this)());
|
||||
}
|
||||
};
|
||||
|
||||
// An MPL iterator which iterates over a sequence whose first element
|
||||
// is gen_this_from_python<T> and the remainder of which is an endless
|
||||
// sequence of gen_arg_from_python
|
||||
template <class T, class Wrap = not_specified>
|
||||
struct method_args_from_python
|
||||
{
|
||||
typedef gen_this_from_python<T,Wrap> type;
|
||||
typedef args_from_python next;
|
||||
};
|
||||
template <class T, class Wrap = not_specified>
|
||||
struct this_ref_arg_from_python : this_ptr_arg_from_python<T,Wrap>
|
||||
{
|
||||
typedef this_ptr_arg_from_python<T,Wrap> base;
|
||||
this_ref_arg_from_python(PyObject* x) : base(x) {}
|
||||
typedef T& result_type;
|
||||
|
||||
result_type operator()() const
|
||||
{
|
||||
return *this->base::operator()();
|
||||
}
|
||||
};
|
||||
|
||||
// An MPL metafunction class which returns a `this' converter
|
||||
// appropriate for ArgType, where the target of the member function is
|
||||
// a class of type T.
|
||||
template <class T, class Wrap = not_specified>
|
||||
struct gen_this_from_python
|
||||
{
|
||||
// Note: there will almost always be an compile-time error if the
|
||||
// argument type is neither a reference nor a pointer, since T*
|
||||
// will be extracted in that case and passed on to the wrapped
|
||||
// function.
|
||||
template <class ArgType> struct apply
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, use_ptr
|
||||
= is_pointer<ArgType>::value
|
||||
|| boost::python::detail::is_reference_to_pointer<ArgType>::value
|
||||
&& boost::python::detail::is_reference_to_const<ArgType>::value
|
||||
&& !boost::python::detail::is_reference_to_volatile<ArgType>::value);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
is_back_reference<ArgType>::value
|
||||
, nullary<arg_from_python<ArgType> >
|
||||
, typename mpl::if_c<
|
||||
use_ptr
|
||||
, this_ptr_arg_from_python<T,Wrap>
|
||||
, this_ref_arg_from_python<T,Wrap>
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
};
|
||||
|
||||
// An MPL iterator which iterates over a sequence whose first element
|
||||
// is gen_this_from_python<T> and the remainder of which is an endless
|
||||
// sequence of gen_arg_from_python
|
||||
template <class T, class Wrap = not_specified>
|
||||
struct method_args_from_python
|
||||
{
|
||||
typedef gen_this_from_python<T,Wrap> type;
|
||||
typedef args_from_python next;
|
||||
};
|
||||
|
||||
template <class VirtualFunction, class Default>
|
||||
struct defaulted_virtual_fn
|
||||
@@ -94,8 +100,6 @@ struct defaulted_virtual_fn
|
||||
Default default_impl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T>
|
||||
struct is_defaulted_virtual_fn
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
# include <boost/python/default_call_policies.hpp>
|
||||
# include <boost/python/object/py_function.hpp>
|
||||
# include <boost/python/signature.hpp>
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ run ../test/embedding.cpp <dll>../build/boost_python
|
||||
: # requirements
|
||||
$(PYTHON_PROPERTIES) ;
|
||||
|
||||
bpl-test polymorphism ;
|
||||
bpl-test auto_ptr ;
|
||||
bpl-test minimal ;
|
||||
bpl-test args ;
|
||||
|
||||
62
test/polymorphism.cpp
Normal file
62
test/polymorphism.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// 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.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct Callback
|
||||
{
|
||||
Callback(PyObject* o) : mSelf(o) {}
|
||||
PyObject* mSelf;
|
||||
};
|
||||
|
||||
struct A
|
||||
{
|
||||
virtual ~A(){}
|
||||
virtual std::string f() { return "A::f()"; }
|
||||
};
|
||||
|
||||
struct ACallback : A, Callback
|
||||
{
|
||||
ACallback (PyObject* self) : Callback(self) {}
|
||||
|
||||
|
||||
std::string f()
|
||||
{
|
||||
return call_method<std::string>(mSelf, "f");
|
||||
}
|
||||
|
||||
std::string default_f()
|
||||
{
|
||||
return A::f();
|
||||
}
|
||||
};
|
||||
|
||||
struct B : A
|
||||
{
|
||||
virtual std::string f() { return "B::f()"; }
|
||||
};
|
||||
|
||||
A& getBCppObj ()
|
||||
{
|
||||
static B b;
|
||||
return b;
|
||||
}
|
||||
|
||||
std::string call_f(A& a) { return a.f(); }
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(polymorphism_ext)
|
||||
{
|
||||
class_<A,boost::noncopyable,ACallback>("A")
|
||||
.def("f", &A::f, &ACallback::default_f)
|
||||
;
|
||||
|
||||
def("getBCppObj", getBCppObj, return_value_policy<reference_existing_object>());
|
||||
|
||||
def("call_f", call_f);
|
||||
}
|
||||
|
||||
//#include "module_tail.cpp"
|
||||
38
test/polymorphism.py
Normal file
38
test/polymorphism.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import unittest
|
||||
from polymorphism_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 testReturnPy(self):
|
||||
|
||||
class C(A):
|
||||
def f(self):
|
||||
return 'C.f'
|
||||
|
||||
c = C()
|
||||
|
||||
self.failUnlessEqual ('C.f', c.f())
|
||||
self.failUnlessEqual ('C.f', call_f(c))
|
||||
|
||||
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