Bearbeitet am 12. Februar
Ich habe gerade einen seltsamen Absturz mit einigen SWIG-generierten Python-Wrappern für einige C ++ - Klassen gemacht. Es scheint, dass die Kombination von SWIG und Python etwas daran interessiert ist, temporäre Werte zu bereinigen. So begierig, dass sie aufgeräumt werden, solange sie noch benutzt werden. Eine deutlich verkürzte Version sieht so aus:
%Vor%Ich starte SWIG (1.3.37) in der .i-Datei und dann in Python:
%Vor% Es scheint, dass in der zweiten Instanz das temporäre Objekt Bar
zerstört wird, bevor wir% c_de%% s theFoo
-Feld lesen können. Dinge in gdb herumjagen, das ist eindeutig was passiert. Und zu dem Zeitpunkt, als wir value
von .value
gelesen haben, hat C ++ bereits Bar().theFoo
zerstört (und mit einer anderen Heap-Zuweisung überschrieben). In meiner aktuellen Situation verursacht dies einen segfault.
Gibt es eine SWIG-Anweisung oder einen Trick, den ich meiner .theFoo
-Datei hinzufügen kann, um Example.i
return Bar().theFoo.value
hier zu machen?
Zweites Update :
Nun, wir wissen, dass das grundlegende Problem ist, dass Python Bar
sofort zerstört. Wenn Bar
in Python implementiert ist, weiß Python's gc, dass es immer noch einen Verweis auf theFoo
gibt, und zerstört es nicht. Aber wenn Bar
in C ++ implementiert ist, ruft python den C ++ - Destruktor auf, der automatisch theFoo
zusammen mit Bar.
Die offensichtliche Lösung besteht also darin, zu verhindern, dass Python Bar
vorzeitig zerstört. Hier ist eine leicht hackische Lösung mit Unterklassen Bar
:
Dies speichert einen Verweis auf die letzte Bar
erstellt, so dass es nicht sofort zerstört wird. Wenn ein neues Bar
erstellt wird, wird das alte gelöscht. (Meine alte Version war albern; keine Notwendigkeit, __del__
dafür zu überschreiben.) Hier ist die Ausgabe (mit cout << "deleting Foo "
in Foo
destructor):
Ich liebe das immer noch nicht. Es könnte besser sein, das "persistente" Verhalten in einem Decorator zu maskieren; Ich habe das auch versucht und es hat funktioniert (wenn Sie den Code sehen wollen, lassen Sie es mich wissen). Es wäre definitiv besser, python irgendwie zu sagen, dass er sich damit beschäftigt, theFoo
selbst zu zerstören, aber ich kann mir nicht vorstellen, wie das geht.
Erstes Update :
Der Umbruchcode sagte mir nichts, also schaute ich in swigexample.py. Das hat auch nichts ergeben. Dinge wurden klarer, als ich versuchte, Bar
in reinem Python zu duplizieren:
Jetzt importieren wir Bar aus pyfoobar:
%Vor%Dieses Verhalten kommt von Python!
Ursprüngliche Antwort :
Es scheint, als gäbe es hier auf jeden Fall einige Garbage-Collection-Kämpfe ... Hier einige Informationen zu SWIG Speicherverwaltung Auf dieser Grundlage sieht es so aus, als ob die Anweisung% newobject das ist, wonach Sie suchen. aber ich habe verschiedene Varianten ausprobiert und konnte es nicht dazu bringen, python über theFoo
zu steuern:
Ich fange an zu vermuten, dass dies beabsichtigt ist; scheint wie diese Linie von dem obigen Link relevant ist:
C hält jetzt einen Hinweis auf die Objekt --- Sie wahrscheinlich nicht wollen Python, um es zu zerstören.
Aber ich bin mir nicht sicher. Ich schaue mir den swigexample_wrap-Code an, um zu sehen, ob ich herausfinden kann, ob ~Bar
aufgerufen wird.
Tags und Links python c++ swig temporary-objects lifetime