[C++-sig] weak_ptr to this in C++ classes extended from python

Holger Brandsmeier brandsmeier at gmx.de
Thu Apr 26 20:49:26 CEST 2012


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 at 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.


More information about the Cplusplus-sig mailing list