[C++-sig] set python attribute from C++

English, Mark Mark.English at rbccm.com
Thu Jul 17 18:04:57 CEST 2008


> -----Original Message-----
> From: c++-sig-bounces at python.org 
> [mailto:c++-sig-bounces at python.org] On Behalf Of Gennadiy Rozental
> Sent: 17 July 2008 08:04
> To: c++-sig at python.org
> Subject: Re: [C++-sig] set python attribute from C++
> 
> <snip>
> On python side I've can now derive from PythonBase:
> 
> class Derived(PythonBase):
>     pass
> 
> Now i am seems to be able to create instances of Derived 
> class and set their field from c++. Does this solution make sence?

I've had similar problems being forced to use other 3rd party shared
pointers. There's a sample somewhere using smart_ptr somewhere which is
a good starting point for discovering the issues.

>From memory since I don't have the code handy, my last effort was
storing a back_reference (using has_back_reference) to the Python
object. As I think Mr Abrahams says, this is the wrong way round since
the Python object is supposed to manage the C++ object's lifetime. It
does however have the advantage of preserving Python object identity,
leading to behaviour like that you describe where exposing the held type
as my_smart_ptr <Foo>, and holding some kind of reference to the
PyObject, allows Python polymorhpism to work.

However, the scenario I never got passed was this:

Python code derives a class "PyFoo" from exposed C++ class "Foo".
Python code creates an instance of "PyFoo" and passes it to C++ code
which expects a my_smart_ptr<Foo>.
C++ code stores my_smart_ptr<Foo> in a container for later retrieval.
Python code deletes its reference to the "PyFoo" instance.
"PyFoo" object reference count falls to 0 and object is no longer used
on Python side.
...Time passes...
Python code calls into C++ code to retrieve object stored in C++
collection of my_smart_ptr<Foo>.
Internally cached PyObject is returned who's reference count was
decremented to 0 above.
Nothing works.

Alternatively a new PyObject wrapper for the C++ "Foo" instance
originally contained within the "PyFoo" instance can be returned, but it
will only appear as a "Foo", and not a "PyFoo".

Following this route requires some mechanism to say from the C++ side
that the PyObject needs to remain valid despite no references to it from
Python. This then leads to issues of how to manage that additional
lifetime information.

All in all the holding a PyObject approach looked promising for a while,
but I suspect it was a mistake.

Before that I tried exposing boost::shared_ptr <my_shared_ptr <Foo> > as
my held_type which I never really got off the ground because of the
difficulty in exposing inheritance relationships with that level of
indirection, so I wouldn't advocate that route either.

I'm sorry that I haven't got any example code handy. I'll try to knock
some up if that doesn't make enough sense, the next time I'm near a
compiler.

I think a better solution is a custom_deleter for your my_smart_ptr,
assuming it supports custom deleters. Perhaps one that extends the one
provided by boost::python.

Also, we're veering away from the topic of how to set python attributes
in C++.

Good luck !
_______________________________________________________________________

This email is intended only for the use of the individual(s) to whom
it is addressed and may be privileged and confidential.

Unauthorised use or disclosure is prohibited. If you receive this
e-mail in error, please advise immediately and delete the original
message without copying, using, or telling anyone about its contents.

This message may have been altered without your or our knowledge and
the sender does not accept any liability for any errors or omissions
in the message.

This message does not create or change any contract.  Royal Bank of
Canada and its subsidiaries accept no responsibility for damage caused
by any viruses contained in this email or its attachments.  Emails may
be monitored.

RBC Capital Markets is a business name used by branches and
subsidiaries of Royal Bank of Canada, including Royal Bank of Canada,
London branch and Royal Bank of Canada Europe Limited. In accordance
with English law requirements, details regarding Royal Bank of Canada
Europe Limited are set out below:

ROYAL BANK OF CANADA EUROPE LIMITED
Registered in England and Wales 995939
Registered Address: 71 Queen Victoria Street, London, EC4V 4DE.
Authorised and regulated by the Financial Service Authority.
Member of the London Stock Exchange




More information about the Cplusplus-sig mailing list