Domanda

Ho due diversi moduli di estensione Python; chiamiamoli A e B. Modulo A contiene un tipo di classe di archiviazione chiamato contenitore che voglio usare all'interno di modulo B come il tipo di ritorno di un metodo di classe.

Non riesco a trovare alcuna documentazione su come dovrei fare questo. I all'incirca seguito questo articolo per creare i moduli / classi, tranne che non aveva dichiarato tutti i metodi sono statici, in modo che sarebbe accessibile: http://nedbatchelder.com/text/whirlext.html

La mia domanda è allora, come posso fare per la creazione di un'istanza di contenitore che posso passare di nuovo come il PyObject * valore di ritorno di un metodo di classe nel modulo B? La definizione container si presenta così:

typedef struct {
    PyObject_HEAD

    storageclass* cnt_;
} container;

Ho provato semplicemente facendo il seguente all'interno del metodo in questione, dove container_init è il metodo che ho registrato come tp_init per la classe contenitore:

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

Tuttavia, secondo l'interprete Python sto tornando alla classe che ho chiamato il metodo su. (Vale a dire, myclassinstance.mymethod () sta tornando myclassinstance).

Sono ovviamente andare su questo nel modo sbagliato, ma non ho idea di ciò che il modo giusto è. Eventuali suggerimenti? Giusto per tagliare fuori qualcuno che sta andando a suggerire - non io non sono interessato a utilizzare SWIG o Boost :: Python. Ho provato già e la classe di archiviazione sottostante per il contenitore non ho giocato bene con entrambi (SWIG non poteva nemmeno analizzarlo). Finora facendo le estensioni me è stato abbastanza indolore, ma sto perplesso su questo.

È stato utile?

Soluzione

Il problema è che type->tp_init non fa quello che si vuole. type->tp_init è chiamato dopo che un oggetto è allocato per fare l'istanziazione. Faresti prima necessario allocare l'oggetto utilizzando type->tp_new, quindi passare tale oggetto come primo argomento a type->tp_init. Dal momento che si passa un puntatore non inizializzato a tp_init, tutte le scommesse sono spenti. In genere non si chiama né funzione direttamente, però, e invece di chiamare uno dei PyObject_Call*() sull'oggetto tipo stesso di creare una nuova istanza. O fornire una funzione C normale per creare una nuova istanza, alla PyFoo_New().

Detto questo, il solito modo di fare intercomunicazione tra due moduli di estensione è farlo tramite l'API Python. Se si desidera che il modulo B di importare e utilizzare modulo A, si chiama PyImport_Import() per ottenere l'oggetto del modulo, PyObject_GetAttrString() per ottenere l'oggetto tipo che ti interessano, e uno dei PyObject_Call*() ad un'istanza. Ogni luogo che si desidera memorizzare un puntatore a quel tipo, si sarebbe solo prendere un PyObject *.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top