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

Bryan Catanzaro bcatanzaro at acm.org
Thu Apr 26 18:43:55 CEST 2012


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.

------------  foo.cpp  ------------
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <iostream>

//Inheriting boost::enable_shared_from_this adds a weak_ptr to the object
//That gets automatically initialized when you construct a shared_ptr
//holding the object.

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;
    }
//This function allows us to get a shared_ptr holding the object
    boost::shared_ptr<A> ptr() {
        return shared_from_this();
    }
};

int A::counter = 0;

using namespace boost::python;

class B {
    boost::shared_ptr<A> m_a;
    static int counter;
public:
    int id;
    //Notice that B accepts an A object directly
    //And asks it for the shared_ptr which holds it.
    B(A& a) : m_a(a.ptr()) {
        id = counter++;
        std::cout << "Constructing B[" << id << "]";
        std::cout << ", which holds A[" << m_a->id << "]" << std::endl;
    }
    ~B() {
        std::cout << "Destructing B[" << id << "]";
        std::cout << ", which holds A[" << m_a->id << "]" << std::endl;
    }
};

int B::counter = 0;

BOOST_PYTHON_MODULE(foo) {
    class_<A, boost::shared_ptr<A> >("A", init<>());
    class_<B>("B", init<A&>());
}
-----------------------------------

------------  test.py  ------------
import foo

class ExtendedA(foo.A):
    def special(self):
        return "successfully extended foo.A"
a0 = foo.A()
a = ExtendedA()
print a.special()
print "an ExtendedA object is a foo.A object: %s" % isinstance(a, foo.A)
b = foo.B(a)
-----------------------------------

On my system the output is:

Constructing A[0]
Constructing A[1]
successfully extended foo.A
an ExtendedA object is a foo.A object: True
Constructing B[0], which holds A[1]
Destructing B[0], which holds A[1]
Destructing A[1]
Destructing A[0]



More information about the Cplusplus-sig mailing list