2
0
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:
Dave Abrahams
2003-08-12 04:36:42 +00:00
parent 9c6650963f
commit 5008dcbdd4
7 changed files with 109 additions and 33 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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>());

View File

@@ -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