diff --git a/include/boost/python/object/make_instance.hpp b/include/boost/python/object/make_instance.hpp index eb420d2f..d63c346a 100644 --- a/include/boost/python/object/make_instance.hpp +++ b/include/boost/python/object/make_instance.hpp @@ -6,9 +6,11 @@ #ifndef MAKE_INSTANCE_DWA200296_HPP # define MAKE_INSTANCE_DWA200296_HPP +# include # include # include # include +# include namespace boost { namespace python { namespace objects { @@ -24,6 +26,9 @@ struct make_instance_impl PyTypeObject* type = Derived::get_class_object(x); + if (type == 0) + return python::detail::none(); + PyObject* raw_result = type->tp_alloc( type, objects::additional_instance_size::value); diff --git a/include/boost/python/object/make_ptr_instance.hpp b/include/boost/python/object/make_ptr_instance.hpp index 25dbd77c..54d3e4d5 100644 --- a/include/boost/python/object/make_ptr_instance.hpp +++ b/include/boost/python/object/make_ptr_instance.hpp @@ -34,6 +34,9 @@ struct make_ptr_instance template static inline PyTypeObject* get_class_object_impl(U const volatile* p) { + if (p == 0) + return 0; + PyTypeObject* derived = get_derived_class_object(is_polymorphic::type(), p); if (derived) return derived; diff --git a/test/shared_ptr.cpp b/test/shared_ptr.cpp index 39da8652..32c9af74 100644 --- a/test/shared_ptr.cpp +++ b/test/shared_ptr.cpp @@ -95,8 +95,53 @@ shared_ptr factory(int n) static int stored_v() { return functions::get()->v(); } static shared_ptr stored_z() { return functions::get(); } +// regressions from Nicodemus + struct A + { + virtual int f() = 0; + static int call_f(shared_ptr& a) { return a->f(); } + }; + + struct B: A + { + int f() { return 1; } + }; + + boost::shared_ptr New(bool make) + { + return boost::shared_ptr( make ? new B() : 0 ); + } + + struct A_Wrapper: A + { + A_Wrapper(PyObject* self_): + A(), self(self_) {} + + int f() { + return call_method< int >(self, "f"); + } + + PyObject* self; + }; + +// ------ + BOOST_PYTHON_MODULE(shared_ptr_ext) { + class_, boost::noncopyable>("A") + .def("call_f", &A::call_f) + .staticmethod("call_f") + ; + + // This is the ugliness required to register a to-python converter + // for shared_ptr. + objects::class_value_wrapper< + shared_ptr + , objects::make_ptr_instance,A> > + >(); + + def("New", &New); + class_("X", init()) .def("value", &X::value) ; diff --git a/test/shared_ptr.py b/test/shared_ptr.py index e86da6df..1d3c1ab2 100644 --- a/test/shared_ptr.py +++ b/test/shared_ptr.py @@ -1,6 +1,11 @@ ''' >>> from shared_ptr_ext import * +>>> a = New(1) +>>> A.call_f(a) +1 +>>> New(0) + >>> type(factory(3)) >>> type(factory(42))