Angenommen, wir haben den Typ Noddy
, der im Tutorial zum Schreiben von C-Erweiterungsmodulen für Python definiert ist . Jetzt wollen wir einen abgeleiteten Typ erstellen und nur die __new__()
Methode von überschreiben Noddy
.
Derzeit verwende ich den folgenden Ansatz (Fehlerprüfung auf Lesbarkeit gestrippt):
PyTypeObject *BrownNoddyType =
(PyTypeObject *)PyType_Type.tp_alloc(&PyType_Type, 0);
BrownNoddyType->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
BrownNoddyType->tp_name = "noddy.BrownNoddy";
BrownNoddyType->tp_doc = "BrownNoddy objects";
BrownNoddyType->tp_base = &NoddyType;
BrownNoddyType->tp_new = BrownNoddy_new;
PyType_Ready(BrownNoddyType);
Das funktioniert, aber ich bin mir nicht sicher, ob es der richtige Weg ist. Ich hätte erwartet, dass ich auch das Py_TPFLAGS_HEAPTYPE
Flag setzen muss, da ich das Typobjekt auf dem Heap dynamisch zuordne, dies jedoch zu einem Segfault im Interpreter führt.
Ich habe auch darüber nachgedacht, explizit type()
using PyObject_Call()
oder ähnliches aufzurufen , aber ich habe die Idee verworfen. Ich müsste die Funktion BrownNoddy_new()
in ein Python-Funktionsobjekt einbinden und eine Wörterbuchzuordnung __new__
zu diesem Funktionsobjekt erstellen , was albern erscheint.
Was ist der beste Weg, um dies zu erreichen? Ist mein Ansatz korrekt? Gibt es eine Schnittstellenfunktion, die ich verpasst habe?
Aktualisieren
Es gibt zwei Themen zu einem verwandten Thema in der Python-Dev-Mailingliste (1) (2) . Aus diesen Threads und einigen Experimenten schließe ich, dass ich nicht festlegen sollte, es Py_TPFLAGS_HEAPTYPE
sei denn, der Typ wird durch einen Aufruf an zugewiesen type()
. In diesen Threads gibt es unterschiedliche Empfehlungen, ob es besser ist, den Typ manuell zuzuweisen oder aufzurufen type()
. Ich würde mich über Letzteres freuen, wenn ich nur wüsste, wie die C-Funktion, die in den tp_new
Steckplatz eingefügt werden soll, empfohlen wird. Für reguläre Methoden wäre dieser Schritt einfach - ich könnte nur PyDescr_NewMethod()
ein geeignetes Wrapper-Objekt erhalten. Ich weiß jedoch nicht, wie ich ein solches Wrapper-Objekt für meine __new__()
Methode erstellen soll - möglicherweise benötige ich die undokumentierte Funktion PyCFunction_New()
, um ein solches Wrapper-Objekt zu erstellen.