Создайте объект, используя Python C API

Скажем, у меня есть макет объекта, определенный как:

typedef struct {
    PyObject_HEAD
    // Other stuff...
} pyfoo;

... и мое определение типа:

static PyTypeObject pyfoo_T = {
    PyObject_HEAD_INIT(NULL)
    // ...

    pyfoo_new,
};

Как мне создать новый экземпляр pyfoo где-нибудь в моем расширении C?


person detly    schedule 12.11.2010    source источник


Ответы (1)


Вызовите PyObject_New(), а затем PyObject_Init().

EDIT: лучше всего использовать вызов объекта класса, как и в самом Python:

/* Pass two arguments, a string and an int. */
PyObject *argList = Py_BuildValue("si", "hello", 42);

/* Call the class object. */
PyObject *obj = PyObject_CallObject((PyObject *) &pyfoo_T, argList);

/* Release the argument list. */
Py_DECREF(argList);
person Frédéric Hamidi    schedule 12.11.2010
comment
Я согласен, что в этом случае документы немного лаконичны. Я обновил свой ответ необходимым вызовом PyObject_Init(). - person Frédéric Hamidi; 12.11.2010
comment
Подождите, PyObject_Init() не принимает никаких аргументов, так как же передать необходимые аргументы инициализации? - person detly; 12.11.2010
comment
@detly, вам нужно вызвать объект класса. Смотрите мой обновленный ответ. - person Frédéric Hamidi; 12.11.2010
comment
Ааа, это имеет больше смысла. Нормально ли получить ошибку компилятора (назначение из несовместимого типа указателя)? - person detly; 12.11.2010
comment
@detly, поскольку PyTypeObject внутренне происходит от PyObject и используется явное приведение, предупреждения быть не должно. Какой у вас компилятор? - person Frédéric Hamidi; 12.11.2010
comment
GCC 4.4.5... и теперь, когда у меня была возможность проверить, это всего лишь предупреждение, а не ошибка. - person detly; 13.11.2010
comment
Если я возвращаю этот экземпляр в функцию Python, я предполагаю, что мне не нужно увеличивать счетчик сохранения, чтобы быть в безопасности? - person jkp; 07.04.2011
comment
@jkp, если я не ошибаюсь, объект класса уже должен был иметь INCREFed объект, который он возвращал, потому что он только что создал его и в первую очередь намеревается передать вам право собственности. Если вы также намерены передать право собственности на новый объект вызывающему объекту, вам также не следует DECREF его DECREF . Подробнее см. на edcjones.tripod.com/refcount.html. - person Frédéric Hamidi; 07.04.2011
comment
однострочный: PyObject_CallFunction((PyObject *)&pyfoo_T, si, hello, 42); объединяет PyObject_CallObject + Py_BuildValue - person Wiktor Tomczak; 05.03.2018
comment
Если есть только один аргумент, вызов Py_BuildValue требует скобок в строке формата. - person dbn; 30.05.2019
comment
Можете ли вы уточнить, что вы подразумеваете под лучшим? Есть ли причина предпочесть CallObject PyObject_New и PyObject_Init, которые вычеркнуты в ответе? - person cheshirekow; 27.05.2020
comment
Этот ответ устарел? не могу найти в документации - person theonlygusti; 17.03.2021