mirror of
https://github.com/boostorg/python.git
synced 2026-01-26 18:52:26 +00:00
Make sure the class object and cast relationships are registered for
virtual function dispatch classes. [SVN r19543]
This commit is contained in:
@@ -20,17 +20,6 @@
|
||||
# include <boost/python/init.hpp>
|
||||
# include <boost/python/args_fwd.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.hpp>
|
||||
# include <boost/mpl/not.hpp>
|
||||
# include <boost/mpl/or.hpp>
|
||||
|
||||
# include <boost/python/object/select_holder.hpp>
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/python/object/make_instance.hpp>
|
||||
@@ -44,6 +33,18 @@
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/force_instantiate.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.hpp>
|
||||
# include <boost/mpl/not.hpp>
|
||||
# include <boost/mpl/or.hpp>
|
||||
# include <boost/mpl/vector/vector10.hpp>
|
||||
|
||||
# include <boost/utility.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
@@ -106,6 +107,27 @@ namespace detail
|
||||
SelectHolder::register_();
|
||||
}
|
||||
|
||||
//
|
||||
// register_wrapper_class -- register the relationship between a
|
||||
// virtual function callback wrapper class and the class being
|
||||
// wrapped.
|
||||
//
|
||||
template <class T>
|
||||
inline void register_wrapper_class(T*, T*, int) {}
|
||||
|
||||
template <class Wrapper, class T>
|
||||
inline void register_wrapper_class(Wrapper*, T*, ...)
|
||||
{
|
||||
objects::register_class_from_python<Wrapper, mpl::vector1<T> >();
|
||||
objects::copy_class_object(type_id<T>(), type_id<Wrapper>());
|
||||
}
|
||||
|
||||
template <class Held, class T>
|
||||
inline void register_wrapper_class(Held* = 0, T* = 0)
|
||||
{
|
||||
register_wrapper_class((Held*)0, (T*)0, 0);
|
||||
}
|
||||
|
||||
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
|
||||
template <class T>
|
||||
struct is_data_member_pointer
|
||||
@@ -562,6 +584,12 @@ inline void class_<T,X1,X2,X3>::register_() const
|
||||
{
|
||||
objects::register_class_from_python<T,bases>();
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME holder_selector::type select_holder;
|
||||
typedef BOOST_DEDUCED_TYPENAME select_holder::type holder;
|
||||
typedef BOOST_DEDUCED_TYPENAME holder::held_type held_t;
|
||||
|
||||
detail::register_wrapper_class<held_t,T>();
|
||||
|
||||
detail::register_class_to_python<T>(
|
||||
mpl::bool_<is_copyable>()
|
||||
# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
|
||||
@@ -58,6 +58,8 @@ struct BOOST_PYTHON_DECL class_base : python::api::object
|
||||
void make_method_static(const char *method_name);
|
||||
};
|
||||
|
||||
BOOST_PYTHON_DECL void copy_class_object(type_info const& src, type_info const& dst);
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
#endif // CLASS_DWA20011214_HPP
|
||||
|
||||
@@ -52,6 +52,7 @@ bool is_null(T* p, int)
|
||||
template <class Pointer, class Value>
|
||||
struct pointer_holder : instance_holder
|
||||
{
|
||||
typedef Value held_type;
|
||||
typedef Value value_type;
|
||||
|
||||
pointer_holder(Pointer);
|
||||
@@ -73,9 +74,7 @@ struct pointer_holder : instance_holder
|
||||
template <class Pointer, class Value>
|
||||
struct pointer_holder_back_reference : instance_holder
|
||||
{
|
||||
private:
|
||||
typedef typename python::pointee<Pointer>::type held_type;
|
||||
public:
|
||||
typedef Value value_type;
|
||||
|
||||
// Not sure about this one -- can it work? The source object
|
||||
|
||||
@@ -37,10 +37,11 @@ namespace boost { namespace python { namespace objects {
|
||||
# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) objects::do_unforward(a##n,0)
|
||||
# endif
|
||||
|
||||
template <class Held>
|
||||
template <class Value>
|
||||
struct value_holder : instance_holder
|
||||
{
|
||||
typedef Held value_type;
|
||||
typedef Value held_type;
|
||||
typedef Value value_type;
|
||||
|
||||
// Forward construction to the held object
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/value_holder.hpp>, 1))
|
||||
@@ -50,13 +51,14 @@ struct value_holder : instance_holder
|
||||
void* holds(type_info);
|
||||
|
||||
private: // data members
|
||||
Held m_held;
|
||||
Value m_held;
|
||||
};
|
||||
|
||||
template <class Held, class BackReferenceType>
|
||||
template <class Value, class Held>
|
||||
struct value_holder_back_reference : instance_holder
|
||||
{
|
||||
typedef Held value_type;
|
||||
typedef Held held_type;
|
||||
typedef Value value_type;
|
||||
|
||||
// Forward construction to the held object
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/value_holder.hpp>, 2))
|
||||
@@ -66,29 +68,29 @@ private: // required holder implementation
|
||||
void* holds(type_info);
|
||||
|
||||
private: // data members
|
||||
BackReferenceType m_held;
|
||||
Held m_held;
|
||||
};
|
||||
|
||||
# undef BOOST_PYTHON_UNFORWARD_LOCAL
|
||||
|
||||
template <class Held>
|
||||
void* value_holder<Held>::holds(type_info dst_t)
|
||||
template <class Value>
|
||||
void* value_holder<Value>::holds(type_info dst_t)
|
||||
{
|
||||
type_info src_t = python::type_id<Held>();
|
||||
type_info src_t = python::type_id<Value>();
|
||||
return src_t == dst_t ? &m_held
|
||||
: find_static_type(&m_held, src_t, dst_t);
|
||||
}
|
||||
|
||||
template <class Held, class BackReferenceType>
|
||||
void* value_holder_back_reference<Held,BackReferenceType>::holds(
|
||||
template <class Value, class Held>
|
||||
void* value_holder_back_reference<Value,Held>::holds(
|
||||
type_info dst_t)
|
||||
{
|
||||
type_info src_t = python::type_id<Held>();
|
||||
Held* x = &m_held;
|
||||
type_info src_t = python::type_id<Value>();
|
||||
Value* x = &m_held;
|
||||
|
||||
if (dst_t == src_t)
|
||||
return x;
|
||||
else if (dst_t == python::type_id<BackReferenceType>())
|
||||
else if (dst_t == python::type_id<Held>())
|
||||
return &m_held;
|
||||
else
|
||||
return find_static_type(x, src_t, dst_t);
|
||||
|
||||
@@ -521,6 +521,16 @@ namespace objects
|
||||
converters.m_class_object = (PyTypeObject*)incref(this->ptr());
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void copy_class_object(type_info const& src, type_info const& dst)
|
||||
{
|
||||
converter::registration& dst_converters
|
||||
= const_cast<converter::registration&>(converter::registry::lookup(dst));
|
||||
|
||||
converter::registration const& src_converters = converter::registry::lookup(src);
|
||||
|
||||
dst_converters.m_class_object = src_converters.m_class_object;
|
||||
}
|
||||
|
||||
void class_base::set_instance_size(std::size_t instance_size)
|
||||
{
|
||||
this->attr("__instance_size__") = instance_size;
|
||||
|
||||
@@ -52,6 +52,28 @@ struct C : A
|
||||
virtual std::string f() { return "C::f()"; }
|
||||
};
|
||||
|
||||
struct D : A
|
||||
{
|
||||
virtual std::string f() { return "D::f()"; }
|
||||
std::string g() { return "D::g()"; }
|
||||
};
|
||||
|
||||
struct DCallback : D, Callback
|
||||
{
|
||||
DCallback (PyObject* self) : Callback(self) {}
|
||||
|
||||
std::string f()
|
||||
{
|
||||
return call_method<std::string>(mSelf, "f");
|
||||
}
|
||||
|
||||
std::string default_f()
|
||||
{
|
||||
return A::f();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
A& getBCppObj ()
|
||||
{
|
||||
static B b;
|
||||
@@ -79,6 +101,8 @@ C& getCCppObj ()
|
||||
return c;
|
||||
}
|
||||
|
||||
A* pass_a(A* x) { return x; }
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(polymorphism_ext)
|
||||
{
|
||||
class_<A,boost::noncopyable,ACallback>("A")
|
||||
@@ -91,6 +115,13 @@ BOOST_PYTHON_MODULE_INIT(polymorphism_ext)
|
||||
.def("f", &C::f)
|
||||
;
|
||||
|
||||
class_<D,bases<A>,DCallback,boost::noncopyable>("D")
|
||||
.def("f", &D::f, &DCallback::default_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>());
|
||||
|
||||
@@ -32,17 +32,21 @@ class PolymorphTest(unittest.TestCase):
|
||||
self.failUnlessEqual(type(factory(1)), A)
|
||||
self.failUnlessEqual(type(factory(2)), C)
|
||||
|
||||
def testReturnPy(self):
|
||||
def test_return_py(self):
|
||||
|
||||
class D(A):
|
||||
class X(A):
|
||||
def f(self):
|
||||
return 'D.f'
|
||||
return 'X.f'
|
||||
|
||||
d = D()
|
||||
x = X()
|
||||
|
||||
self.failUnlessEqual ('D.f', d.f())
|
||||
self.failUnlessEqual ('D.f', call_f(d))
|
||||
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())
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# remove the option which upsets unittest
|
||||
|
||||
Reference in New Issue
Block a user