I think the problem is that aa is no longer an ExtendedA object, because when you call ptr() it returns a pointer to the base C++ A class, not the derived class. I think at this point it's probably best to reconsider the problem and come up with a simpler solution. Why do you want to expose the ptr method to Python anyway? - bryan On Thu, Apr 26, 2012 at 11:49 AM, Holger Brandsmeier <brandsmeier@gmx.de> wrote:
Bryan,
my problems happen as soon as I need to use wrappers. I really need the class that I extend in python to implement some pure virtual function in the C++ class. I extended your code and refined what is going wrong. I tried several Variants with different errors, I used #defines to show you all 4 versions, next to each Variant I put a C++ comment of what is going wrong.
So here it is:
------------ foo.cpp ------------ #include <boost/python.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <iostream>
using namespace boost::python;
class A : public boost::enable_shared_from_this<A> { static int counter; public: int id; A() { id = counter++; std::cout << "Constructing A[" << id << "]" << std::endl; } ~A() { std::cout << "Destructing A[" << id << "]" << std::endl; } boost::shared_ptr<A> ptr() { return shared_from_this(); } #define VARIANT0 #ifdef VARIANT0 // this variant works nicely with VARIANT1 below (compiles and // no error for `aa = a.ptr()`), but it produces wrong results, // i.e. `77` is returned for `aa.foo()` although it should have // been `33`. virtual int foo() { return 77; } #else virtual int foo() = 0; #endif };
struct AWrapper : public A, public boost::python::wrapper<A> { virtual int foo() { if( override f = this->get_override("foo") ) { return f(); } else { return 42; } } };
int A::counter = 0;
using namespace boost::python;
BOOST_PYTHON_MODULE(foo) { #define VARIANT1 //#define VARIANT2 //#define VARIANT3
#ifdef VARIANT1 // The following line doesn't compites it gives the error: // error: cannot allocate an object of abstract type ‘A’ class_<AWrapper, boost::shared_ptr<A>, boost::noncopyable >("A", init<>()) #endif #ifdef VARIANT2 // the following compiles, but produces an error in python, when executing // aa = a.ptr(); // RuntimeError: tr1::bad_weak_ptr class_<AWrapper, boost::noncopyable >("A", init<>()) #endif #ifdef VARIANT3 // the following compiles, but produces an error in python, when executing // aa = a.ptr(); // TypeError: No to_python (by-value) converter found for C++ type: boost::shared_ptr<A> class_<AWrapper, boost::shared_ptr<AWrapper>, boost::noncopyable
("A", init<>()) #endif .def("ptr", &A::ptr) .def("foo", &A::foo) ; }
------------ foo.py ------------ import foo
class ExtendedA(foo.A): def foo(self): return 33;
a0 = foo.A() a = ExtendedA() aa = a.ptr(); print a.foo() del a print aa.foo() -----------------------------------
Do you have any suggestion how to get this working? -Holger
On Thu, Apr 26, 2012 at 18:43, Bryan Catanzaro <bcatanzaro@acm.org> wrote:
Holger Brandsmeier <brandsmeier <at> gmx.de> writes:
Dear list,
how is it possible to have a class in C++ that can be extended from python and that stores a weak_ptr to itself?
Have you tried using boost::enable_shared_from_this? The following example code seems to do what you want.
Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig