You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have a setup where I'm using a std::weak_ptr to keep track of objects that can originate in C++ or Python, and in a certain situation the weak_ptr expires even if the corresponding Python object still exists. Am I doing something wrong or is there a Pybind11 issue? Any help will be appreciated.
I have a minimum working example to demonstrate the issue. The C++ base class is thing, and there's a "holder" class that contains a std::weak_ptr< thing >. I don't want the holder to influence the lifetime of the thing it holds, hence using weak_ptr. For the binding, I want to have a trampoline so I can have virtual functions handled properly in Python. For this example I've included a derived thing in Python called DerivedThing.
The issue I'm running into is that after passing a DerivedThing to thing_holder and returning to Python, when I try to access the DerivedThing via its pointer in thing_holder again, the weak_ptr has expired.
Here's the minimum working example. First the C++ classes:
And finally the Python script that includes the derived thing class:
classDerivedThing(dripline.core.Thing):
def__init__(self):
dripline.core.Thing.__init__(self)
defget_type(self):
return"DerivedThing"if__name__=='__main__':
holder=thing_module.ThingHolder()
print('Creating a thing')
thing=thing_module.Thing()
print(f'Type: {thing.get_type()}')
print('Giving thing to the holder')
holder.set_thing(thing)
print('Printing after a return to python')
holder.print_thing()
print('\n')
print('Creating a derived thing')
derthing=DerivedThing()
print(f'Type: {derthing.get_type()}')
print('(Giving derived thing to the holder')
holder.set_thing(derthing)
print('Printing after a return to python')
holder.print_thing()
The expected output is:
Creating a thing
Type: thing
Setting thing then printing
thing expired? 0
type is thing
Printing after a return to python
thing expired? 0
type is thing
Creating a derived thing
Type: DerivedThing
Setting thing then printing
thing expired? 0
type is DerivedThing
Printing after a return to python
thing expired? 0
type is DerivedThing
The actual output is:
Creating a thing
Type: thing
Setting thing then printing
thing expired? 0
type is thing
Printing after a return to python
thing expired? 0
type is thing
Creating a derived thing
Type: DerivedThing
Setting thing then printing
thing expired? 0
type is DerivedThing
Printing after a return to python
thing expired? 1
The issue is the last line, which indicates that the weak_ptr is no longer aware that the object still exists. My hypothesis is that even though we're using py::smart_holder in the thing binding, the fact that we only keep weak_ptr< thing > in the C++ results in the C++ side losing track of the Python objects, whereas if we had a shared_ptr< thing >, according to the documentation, it would still work.
I tested a these variations:
Thing created in Python (as in the above example) -- works
DerivedThing created in Python (as in the above example) -- does not work
DerivedThing created in Python with no thing_trampoline -- works (except there's no virtual function overriding)
DerivedThing created in Python where thing_trampoline also inherits from py::trampoline_self_life_support (commented out in the above code) -- does not work
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I have a setup where I'm using a
std::weak_ptr
to keep track of objects that can originate in C++ or Python, and in a certain situation theweak_ptr
expires even if the corresponding Python object still exists. Am I doing something wrong or is there a Pybind11 issue? Any help will be appreciated.I have a minimum working example to demonstrate the issue. The C++ base class is
thing
, and there's a "holder" class that contains astd::weak_ptr< thing >
. I don't want the holder to influence the lifetime of thething
it holds, hence usingweak_ptr
. For the binding, I want to have a trampoline so I can have virtual functions handled properly in Python. For this example I've included a derivedthing
in Python calledDerivedThing
.The issue I'm running into is that after passing a
DerivedThing
tothing_holder
and returning to Python, when I try to access theDerivedThing
via its pointer inthing_holder
again, theweak_ptr
has expired.Here's the minimum working example. First the C++ classes:
Next, the trampoline class and Python bindings:
And finally the Python script that includes the derived thing class:
The expected output is:
The actual output is:
The issue is the last line, which indicates that the
weak_ptr
is no longer aware that the object still exists. My hypothesis is that even though we're usingpy::smart_holder
in thething
binding, the fact that we only keepweak_ptr< thing >
in the C++ results in the C++ side losing track of the Python objects, whereas if we had ashared_ptr< thing >
, according to the documentation, it would still work.I tested a these variations:
Thing
created in Python (as in the above example) -- worksDerivedThing
created in Python (as in the above example) -- does not workDerivedThing
created in Python with nothing_trampoline
-- works (except there's no virtual function overriding)DerivedThing
created in Python wherething_trampoline
also inherits frompy::trampoline_self_life_support
(commented out in the above code) -- does not workBeta Was this translation helpful? Give feedback.
All reactions