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 <brandsme...@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 <bcatanz...@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
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to