[C++-sig] Re: Pointer to existing Python object

David Abrahams dave at boost-consulting.com
Thu Apr 28 23:09:21 CEST 2005


Andreas Beyer <beyer at imb-jena.de> writes:

> Hi:
>
> I know that there has been some discussion on this subject on c++ sig. 
> However, I could not find a solution for my specific problem and maybe 
> there is no solution.
>
> Here we go:
>
> I have a container class B that creates instances of class A - both
> in C++. In Python I can get instances of A from B with a get()
> method. I would like to get an existing Python object whenever such
> object existis and I would like to get a new Python object if no
> Python object for A exists.

This is hard to do.  I see that you're using shared_ptr and that's a
good start.  What you need to do, the moment a shared_ptr is about to
be released to Python, is replace it:

   template <class T>
   hold_python(shared_ptr<T>& x)
   {
       x = extract<shared_ptr<T> >( python::object(x) );
   }

> An example:
>
>
> using namespace boost;
>
> class A : public enable_shared_from_this<A> {
>  public:
>     A() : val(0) {};
>     int val;
>     typedef shared_ptr<A> A_ptr;
>     A_ptr self() {
>        A_ptr self;
>        self = shared_from_this();
>        return self;
>      }
>
> };
>
>
> class B {
>    public:
>      B() {
>           a = A::A_ptr(new A());
>      }
>      A::A_ptr a;
>      void set(A::A_ptr a) {
>          this->a = a;
>      }
>
>      A::A_ptr get() {
>          return a->self();

What was wrong with 

          return a;

here?

>      }
> };
>

A::A_ptr get_b_a(B& b)
{
    hold_python(b.a);
    return b.a;
}

> BOOST_PYTHON_MODULE(ptr_test) {
>  python::class_<A> ("A")
>    .def_readwrite("val", &A::val)
>  ;
>  python::register_ptr_to_python< A::A_ptr >();
>
>  python::class_<B>("B")
>     .def("set", &B::set)
>     .def("get", &B::get)

      .def("get", get_b_a) // <=== here
>  ;
> }
>
>
> In Python I would like to do this:
>
>>>> b = B()
>>>> a1 = b.get() # obtain instance of class A
>>>> a2 = b.get() # get the *same Python instance* again
>>>> assert(a1==a2)
> Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
> AssertionError
>>>>
>
> The internal representations of instances of A are the same! Whenever I 
> access a C++ member of A I am actually accessing the same object.  So I 
> can do this:
>>>> a1.val = 42 # change internal reference
>>>> print a2.val
> 42
>>>>
> However, I cannot do this:
>>>> a1.foo = 42
>>>> print a2.foo
> Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
> AttributeError: 'A' object has no attribute 'foo'
>>>>
>
> I think instances of B have to check if there is already an existing 
> Python object. In that case  B (or a wrapper of B) should return the 
> existing Python object (i.e. instances of python::object). Is there a 
> way to find such an existing instance?

HTH,

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com




More information about the Cplusplus-sig mailing list