Вопрос

У меня есть два разных модуля расширения Python;назовем их А и Б.Модуль A содержит тип класса хранения, называемый контейнером, который я хочу использовать в модуле B в качестве возвращаемого типа метода класса.

Кажется, я не могу найти никакой документации о том, как мне это сделать.Я примерно следовал этой статье при создании модулей/классов, за исключением того, что я не объявил все методы статическими, чтобы они были доступны: http://nedbatchelder.com/text/whirlext.html

Тогда у меня вопрос: как мне создать экземпляр контейнера, который я могу передать обратно как возвращаемое значение PyObject* метода класса в модуле B?Определение контейнера выглядит следующим образом:

typedef struct {
    PyObject_HEAD

    storageclass* cnt_;
} container;

Я попытался просто сделать следующее в рассматриваемом методе, гдеContainer_init — это метод, который я зарегистрировал как tp_init для класса контейнера:

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

Однако, согласно интерпретатору Python, я возвращаю класс, в котором вызвал метод.(т. е. myclassinstance.mymethod() возвращает myclassinstance).

Очевидно, я поступаю неправильным путем, но понятия не имею, какой путь правильный.Какие-либо предложения?Просто чтобы отрезать тех, кто предложит это: нет, я не заинтересован в использовании SWIG или Boost::Python.Я уже пробовал это, и базовый класс хранения для контейнера тоже не очень хорошо работал (SWIG даже не смог его проанализировать).До сих пор самостоятельное расширение было довольно безболезненным, но я в тупике.

Это было полезно?

Решение

Ваша проблема в том, что type->tp_init не делает то, что ты хочешь. type->tp_init вызывается после выделения объекта для создания экземпляра.Сначала вам нужно будет выделить объект, используя type->tp_new, затем передайте этот объект в качестве первого аргумента type->tp_init.Поскольку вы передаете неинициализированный указатель на tp_init, все ставки сделаны.Однако обычно вы не вызываете ни одну из функций напрямую, а вместо этого вызываете одну из PyObject_Call*() на самом объекте типа, чтобы создать новый экземпляр.Или предоставить нормальную функцию C для создания нового экземпляра, а-ля PyFoo_New().

Тем не менее, обычный способ взаимодействия между двумя модулями расширения — это сделать это через API Python.Если вы хотите, чтобы модуль B импортировал и использовал модуль A, вы вызываете PyImport_Import() чтобы получить объект модуля, PyObject_GetAttrString() чтобы получить интересующий вас объект типа и один из PyObject_Call*() чтобы создать его экземпляр.В любом месте, где вы хотите сохранить указатель на этот тип, вам просто нужно взять PyObject *.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top