Question

J'ai deux modules d'extension Python différents; appelons-les A et B. Le module A contient un type de classe de stockage appelé conteneur que je veux utiliser au sein du module B comme type de retour d'une méthode de classe.

Je ne peux pas sembler trouver de la documentation sur la façon dont je suis censé le faire. Je suivais à peu près cet article pour créer les modules / classes, sauf que je ne déclare toutes les méthodes comme statiques, ils seraient accessibles: http://nedbatchelder.com/text/whirlext.html

Ma question est alors, comment puis-je faire pour créer une instance de conteneur que je peux passer en arrière comme PyObject * valeur de retour d'une méthode de classe dans le module B? La définition du conteneur ressemble à ceci:

typedef struct {
    PyObject_HEAD

    storageclass* cnt_;
} container;

J'ai essayé de faire simplement ce qui suit dans la méthode en question, où container_init est la méthode que je me suis inscrit comme tp_init pour la classe conteneur:

pycnt::container* retval;
pycnt::container_init(retval, NULL, NULL);
return (PyObject*)retval;

Toutefois, selon l'interpréteur Python Je reviens de la classe que j'ai appelé la méthode sur. (À savoir, myclassinstance.mymethod () retourne myclassinstance).

Je vais évidemment sur ce dans le mauvais sens, mais je ne sais pas ce que le bon sens est. Aucune suggestion? Juste pour couper tout le monde ce va suggérer - non, je ne suis pas intéressé à utiliser SWIG ou Boost :: Python. J'ai essayé déjà et la classe de stockage sous-jacent pour conteneur ne joue pas bien avec (SWIG n'a pas pu analyser même pas). Ce faisant bien les extensions moi-même a été assez indolore, mais je suis perplexe sur celui-ci.

Était-ce utile?

La solution

Votre problème est que type->tp_init ne fait pas ce que vous voulez. type->tp_init est appelé après qu'un objet est affecté à faire l'instanciation. Vous auriez d'abord d'affecter l'objet à l'aide type->tp_new, puis passer cet objet comme premier argument à type->tp_init. Puisque vous passez un pointeur non initialisé à tp_init, tous les paris sont ouverts. En général, vous n'appelez pas non plus fonction directement, cependant, et au lieu d'appeler l'un des PyObject_Call*() sur l'objet de type lui-même pour créer une nouvelle instance. Ou fournir une fonction normale de C pour créer une nouvelle instance, à la PyFoo_New().

Cela dit, la façon habituelle de faire intercommunication entre deux modules d'extension est de le faire via l'API Python. Si vous voulez module B d'importer et d'utiliser le module A, vous appelez PyImport_Import() pour obtenir l'objet de module, PyObject_GetAttrString() pour obtenir que vous aimez l'objet de type, et l'un des PyObject_Call*() à l'instanciation. Tout endroit où vous voulez stocker un pointeur sur ce type, vous serait juste prendre un PyObject *.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top