Die Verwendung mehrerer Module / Typen mit Python-C-API?
-
22-09-2019 - |
Frage
Ich habe zwei verschiedene Python-Erweiterungsmodule bekommt; nennen wir sie A und B Modul A enthält einen Speicherklasse Typ Container genannt, dass ich innerhalb von Modul B als Rückgabetyp einer Klassenmethode verwendet werden soll.
Ich kann keine Dokumentation zu finden scheinen, wie ich soll, dies zu tun. Ich folgte in etwa diesem Artikel werden die Module / Klassen zu erstellen, außer ich nicht alle Methoden als statisch deklarieren haben, so würden sie zugänglich sein: http://nedbatchelder.com/text/whirlext.html
Meine Frage ist dann, wie gehe ich über eine Instanz des Behälters zu schaffen, dass ich als PyObject * Rückgabewert einer Klassenmethode in Modul B passieren zurück kann? Die Container-Definition sieht wie folgt aus:
typedef struct {
PyObject_HEAD
storageclass* cnt_;
} container;
Ich habe versucht, einfach zu tun, dass sie innerhalb der Methode in Frage, wo container_init ist die Methode, die ich als tp_init für die Container-Klasse registriert haben:
pycnt::container* retval;
pycnt::container_init(retval, NULL, NULL);
return (PyObject*)retval;
Jedoch nach dem Python-Interpreter mir die Klasse immer wieder, dass ich die Methode aufgerufen. (D.h. myclassinstance.mymethod () zurückkehrt myclassinstance).
Ich werde dies offensichtlich über die falsche Art und Weise, aber ich habe keine Ahnung, was der richtige Weg ist. Irgendwelche Vorschläge? Nur um zu schneiden jemand aus, das wird es vorschlagen - kein bin ich nicht in mit SWIG oder Boost-interessiert :: Python. Ich habe versucht, dass bereits und die darunter liegende Speicherklasse für Container nicht spielte gut mit entweder (SWIG kann es nicht einmal analysieren). Bisher die Erweiterungen tun mir ziemlich schmerzlos gewesen, aber ich bin auf dieser stumped.
Lösung
Ihr Problem ist, dass type->tp_init
nicht tut, was Sie wollen. type->tp_init
wird aufgerufen, nachdem ein Objekt zugeordnet ist, die Instanziierung zu tun. Sie würden zunächst das Objekt mit type->tp_new
zuweisen müssen, übergeben Sie dann das Objekt als erstes Argument zu type->tp_init
. Da Sie eine nicht initialisierte Zeiger auf tp_init
passieren, sind alle Wetten ab. Sie rufen typischerweise nicht so oder Funktion direkt, aber, und anstelle eines PyObject_Call*()
auf dem Typ Objekt aufrufen selbst eine neue Instanz zu erstellen. Oder bietet eine normale C-Funktion eine neue Instanz, a la PyFoo_New()
zu erstellen.
sagte, dass die übliche Art und Weise Kommunikation zwischen zwei Erweiterungsmodulen zu tun, ist es durch das Python-API zu tun. Wenn Sie das Modul B auf Import und Verwendung Modul A wollen, rufen Sie PyImport_Import()
das Modul-Objekt zu erhalten, PyObject_GetAttrString()
den Typ-Objekt zu erhalten, die Sie interessieren, und einer von PyObject_Call*()
es zu instanziiert. Jeder Ort, den Sie einen Zeiger auf diese Art speichern möchten, müssen Sie nur eine PyObject *
nehmen.