6

Nur für den Schreck, ich habe beschlossen, eine Scheme binding to libpython zu erstellen, so dass Sie Python in Scheme-Programme einbetten können. Ich kann bereits in die C-API von Python einsteigen, habe aber nicht wirklich an Speicherverwaltung gedacht.Gibt es beim Umgang mit C-Code irgendwelche Python-Referenzzählungen/Garbage Collection?

Die Art und Weise mzscheme des FFI funktioniert, ist, dass ich eine Funktion aufrufen kann, und wenn die Funktion einen Zeiger auf eine PyObject zurückgibt, dann kann ich es automatisch den Referenzzähler erhöht. Dann kann ich einen Finalizer registrieren, der die Referenzzählung dekrementiert, wenn das Scheme-Objekt Müll gesammelt wird. Ich habe mir die documentation for reference counting angeschaut und sehe auf den ersten Blick keine Probleme damit (obwohl es in manchen Fällen nicht optimal ist). Gibt es irgendwelche Fehler, die ich vermisse?

Auch habe ich Probleme, Kopf oder Zahl der . Welche Dinge muss ich hier beachten? Insbesondere, wie mache ich Python bewusst, dass ich einen Verweis auf etwas habe, so dass es es nicht sammelt, während ich es noch benutze?

Antwort

7

Ihr Link zu http://docs.python.org/extending/extending.html#reference-counts ist der richtige Ort. In den Abschnitten Erweitern und Einbetten und Python/C-API der Dokumentation wird erläutert, wie die C-API verwendet wird.

Referenzzählung ist einer der ärgerlichen Teile bei der Verwendung der C-API. Das Hauptproblem besteht darin, alles klar zu halten: Abhängig von der API-Funktion, die Sie aufrufen, können Sie den Verweis auf das Objekt, das Sie erhalten, besitzen oder nicht besitzen. Achten Sie darauf, zu verstehen, ob Sie es besitzen (und somit nicht vergessen können, es zu DEKREIEREN oder etwas zu geben, das es stehlen wird) oder es zu leihen (und es INCREF, um es zu behalten und möglicherweise während Ihrer Funktion zu benutzen). Die am häufigsten auftretenden Fehler sind: 1) Sich falsch zu erinnern, ob Sie eine Referenz besitzen, die von einer bestimmten Funktion zurückgegeben wird, und 2) zu glauben, dass Sie sicher sind, eine Referenz länger ausleihen zu können als Sie.

Sie müssen nichts Besonderes für den zyklischen Garbage Collector tun. Es dient nur dazu, einen Fehler in der Referenzzählung zu beheben und benötigt keinen direkten Zugriff.

+0

Also ... Python verwendet Referenzzählung * und * ein Garbage Collector für zyklische Struktur? Das ist ein ziemlich großer Fehler. Die Design-Art. In jedem Fall hört sich das so an, als würde es für Jason viel mehr "Spaß" machen, wenn irgendwelche Werte, die an einem python-seitigen Zyklus beteiligt sind, einem Schema ausgesetzt sind. –

+0

Gute Info. Solange ich alles INKRAFIERE, wenn ich es bekomme und DECREF alles, wenn ich damit fertig bin, sollte ich in Ordnung sein? Oder gibt es irgendwelche Probleme, denen ich begegnen könnte? –

+2

@Jason, nur INCREF * geliehen * Referenzen. Einige Funktionen geben * neue * Referenzen zurück, die bereits INCREF sind. INCREF'ing sie würde zu einem Speicherverlust führen. –

3

Die größte Gotcha, die ich mit Ref zählen und die C-API kennen, ist die __del__ Sache. Wenn Sie einen geliehenen Bezug auf etwas haben, denken Sie, dass Sie ohne INCREF'ing davonkommen können, weil Sie die GIL nicht aufgeben, während Sie diese Referenz verwenden. Wenn Sie jedoch ein Objekt löschen (z. B. indem Sie es aus einer Liste entfernen), ist es möglich, dass Sie einen __del__-Aufruf auslösen, durch den möglicherweise die Referenz entfernt wird, die Sie unter Ihren Füßen ausleihen. Sehr trickreich.

Wenn Sie alle geliehenen Referenzen INCREF (und dann DECREF, natürlich), sobald Sie sie erhalten, sollte es kein Problem geben.