SIP invalidates a Python wrapper only from the destructor of the generated shadow subclass, and that subclass is instantiated only when Python constructs the object (sipSimpleWrapper_init sets from_cpp = FALSE only on the Python-construction path). An instance returned from C++ and wrapped through sipConvertFromType() gets a plain wrapper with no shadow, so nothing notifies it when the underlying C++ object is destroyed by C++ code the binding doesn't control.
This shows up in wxPython/Phoenix for a few classes that are normally created inside wxWidgets' own C++ and hardly ever constructed directly from Python (wxSizerItem, wxMenuItem, wxToolBarToolBase): the Python wrapper stays valid-looking (sip.isdeleted() returns False) after the C++ object is gone.
I looked at sipEventWrappedInstance/sipEventCollectingWrapper (sip/siplib/sip.h) as a possible binding-side fix, registered per type via sipRegisterEventHandler. sipEventWrappedInstance fires inside sipSimpleWrapper_init, right in the from_cpp branch, so it reliably marks the moment a wrapper with no shadow is created. But it doesn't solve the underlying problem: there's no matching per-object hook on the C++ side that fires on destruction regardless of construction path, so there's nothing for it to attach a destruction notification to.
Two threads with the full detail:
Posting here for a second opinion: is there an existing SIP mechanism that reaches this case, or is a per-object destruction hook (something like Qt's QPointer/wx's wxTrackable) on the C++ side genuinely required?
SIP invalidates a Python wrapper only from the destructor of the generated shadow subclass, and that subclass is instantiated only when Python constructs the object (
sipSimpleWrapper_initsetsfrom_cpp = FALSEonly on the Python-construction path). An instance returned from C++ and wrapped throughsipConvertFromType()gets a plain wrapper with no shadow, so nothing notifies it when the underlying C++ object is destroyed by C++ code the binding doesn't control.This shows up in wxPython/Phoenix for a few classes that are normally created inside wxWidgets' own C++ and hardly ever constructed directly from Python (
wxSizerItem,wxMenuItem,wxToolBarToolBase): the Python wrapper stays valid-looking (sip.isdeleted()returnsFalse) after the C++ object is gone.I looked at
sipEventWrappedInstance/sipEventCollectingWrapper(sip/siplib/sip.h) as a possible binding-side fix, registered per type viasipRegisterEventHandler.sipEventWrappedInstancefires insidesipSimpleWrapper_init, right in thefrom_cppbranch, so it reliably marks the moment a wrapper with no shadow is created. But it doesn't solve the underlying problem: there's no matching per-object hook on the C++ side that fires on destruction regardless of construction path, so there's nothing for it to attach a destruction notification to.Two threads with the full detail:
Posting here for a second opinion: is there an existing SIP mechanism that reaches this case, or is a per-object destruction hook (something like Qt's
QPointer/wx'swxTrackable) on the C++ side genuinely required?