boost::python, returning new PyObject references

David Abrahams david.abrahams at rcn.com
Sun Jan 6 17:59:12 CET 2002


----- Original Message -----
From: "Arnaldur Gylfason" <arnaldur at decode.is>
To: "David Abrahams" <david.abrahams at rcn.com>
Sent: Sunday, January 06, 2002 11:16 AM
Subject: Re: boost::python, returning new PyObject references


>
>
> __ You wrote __
>
> > This still leaves the issue of the callbacks in mutable_proxy.
> > We could change get() and reference() to return just the result of the
> > callback, but in the case of get(), the Python reference would be
> borrowed,
> > since the corresponding
> > ref would be a temporary object.
>
> That doesn't borrow a reference. The whole point of ref is that references
> are never borrowed, so it never has to worry about how to properly manage
> reference counts. A borrowed reference is one whose count is not managed
> because you are counting on the lifetime of some other owner to keep it
> alive.
>
> > The underlying sequence/mapping still
> > would hold it and therefore cause the refcount to be >=1.
> > You ok with returning a borrowed reference in get() for mutable_proxy?
> > (that would mean m_p in object_base does not have to be mutable).
>
> I guess I don't understand what you're doing again.
>
> BTW, it looks like mutable_proxy has a function for += and =, but not,
> e.g.,
> for -=. Mistake?
> _______________
>
> the get would be:
>
> PyObject* get()
> {
>      return get_().get();
> }
>
> get_() is the callback that calls get_item on sequence/mapping and returns
> a ref.
> The return value is not stored. Thus it is a temporary.
> By directly calling get() on this temporary ref we get the PyObject* but
> the mutable_proxy does not own it.
> Only the underlying sequence/mapping owns it. That is what I was referring
> to by a borrowed reference.

Oh, I understand now! Do we really want to expose a function which directly
returns a PyObject* at this level? My feeling is that we don't... but I see
that the existing design does it :-(.

Anyway, it makes sense that if we /do/ have such a function, it should
return a borrowed reference. I'm not sure that there's any relationship to
the fact that the ref is a temporary, though. Does that change anything?

> Regarding -=, it is true that it is missing (along with *=, /= etc.).
> += is there to confirm the design. The interface is not complete.
> I was thinking about finishing it later.
> Similar remarks go for the binary operators, only operator+ has been
> implemented.

OK. It seems to me that it should be possible to handle all of these issues
with a single implementation of the inplace operators used for both numbers
and proxies. You just always go through a virtual function (or callback) to
get the PyObject* to operate on.

BTW, do you understand how the following works under-the-covers in Python? I
don't:

>>> x = [ 1 , 2 ]
>>> x[1] += 3
>>> x
[1, 5]

Since integers are immutable, it seems to me that x[1] has to return some
sort of proxy. I guess that could work as long as

>>> x[1] = 2

caused a call to PyObject_SetItem instead of producing the proxy...

I ask about this because we clearly want the same usage to work in C++
through our wrappers.

-Dave





More information about the Cplusplus-sig mailing list