Pergunta

Eu tenho dois módulos de extensão Python diferentes; Vamos chamá -los de A e B. O módulo A contém um tipo de classe de armazenamento chamado contêiner que eu desejo usar no módulo B como o tipo de retorno de um método de classe.

Não consigo encontrar nenhuma documentação sobre como devo fazer isso. Eu segui aproximadamente este artigo para criar os módulos/classes, exceto que não declarei todos os métodos como estáticos, para que eles estejam acessíveis: http://nedbatchelder.com/text/whirlext.html

Minha pergunta é então, como faço para criar uma instância de contêiner que eu possa passar de volta como o valor de retorno Pyobject* de um método de classe no módulo B? A definição de contêiner é assim:

typedef struct {
    PyObject_HEAD

    storageclass* cnt_;
} container;

Tentei simplesmente fazer o seguinte no método em questão, onde o container_init é o método que eu registrei como tp_init para a classe de contêiner:

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

No entanto, de acordo com o intérprete Python, estou recebendo a aula em que chamei o método. (ou seja, myclassinstance.mymethod () está retornando myclassinstance).

Obviamente, estou fazendo isso da maneira errada, mas não tenho idéia do caminho certo. Alguma sugestão? Só para cortar alguém que vai sugerir - não, não estou interessado em usar Swig ou Boost :: Python. Eu já tentei isso e a classe de armazenamento subjacente para o contêiner não jogava bem com a mesma coisa (o SWIG nem conseguia analisá -lo). Até agora, fazer as extensões eu mesmo tem sido bastante indolor, mas estou perplexo com isso.

Foi útil?

Solução

Seu problema é que type->tp_init não faz o que você quer. type->tp_init é chamado depois que um objeto é alocado para fazer a instanciação. Você primeiro teria que alocar o objeto usando type->tp_new, depois passe esse objeto como o primeiro argumento para type->tp_init. Desde que você passa um ponteiro não inicializado para tp_init, todas as apostas estão encerradas. Você normalmente não chama nenhuma função diretamente, e, em vez disso, chama um dos PyObject_Call*() no próprio objeto de tipo para criar uma nova instância. Ou forneça uma função C normal para criar uma nova instância, uma la PyFoo_New().

Dito isto, a maneira usual de fazer intercomunicação entre dois módulos de extensão é fazê -lo através da API Python. Se você deseja que o Módulo B importe e use o módulo A, você liga PyImport_Import() Para obter o objeto do módulo, PyObject_GetAttrString() para obter o objeto de tipo que você se importa e um dos PyObject_Call*() para instanciar isso. Qualquer lugar que você queira armazenar um ponteiro para esse tipo, você apenas aceitaria um PyObject *.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top