Я столкнулся с той же проблемой, когда изменял расширение для совместимости с Python 3, и нашел эту страницу, когда пытался ее решить.
В конце концов я решил эту проблему, прочитав исходный код интерпретатора Python, PEP 0384 и документацию для C-API .
Установка флага Py_TPFLAGS_HEAPTYPE
говорит интерпретатору преобразовать ваш PyTypeObject
в PyHeapTypeObject
, который содержит дополнительные члены, которые также должны быть выделены. В какой-то момент интерпретатор пытается обратиться к этим дополнительным элементам, и, если вы оставите их нераспределенными, это вызовет ошибку сегмента.
В Python 3.2 представлены структуры C PyType_Slot
и PyType_Spec
и функция C PyType_FromSpec
, которые упрощают создание динамических типов. В двух словах, вы используете PyType_Slot
и PyType_Spec
, чтобы указать tp_*
членов PyTypeObject
, а затем вызываете PyType_FromSpec
, чтобы выполнить грязную работу по выделению и инициализации памяти.
Начиная с PEP 0384, мы имеем:
typedef struct{
int slot; /* slot id, see below */
void *pfunc; /* function pointer */
} PyType_Slot;
typedef struct{
const char* name;
int basicsize;
int itemsize;
int flags;
PyType_Slot *slots; /* terminated by slot==0. */
} PyType_Spec;
PyObject* PyType_FromSpec(PyType_Spec*);
(Вышеприведенное не является буквальной копией из PEP 0384, которая также включает const char *doc
в качестве члена PyType_Spec
. Но этот член не указан в исходном коде.)
Чтобы использовать их в исходном примере, предположим, что у нас есть структура C BrownNoddy
, которая расширяет структуру C для базового класса Noddy
. Тогда мы бы получили:
PyType_Slot slots[] = {
{ Py_tp_doc, "BrownNoddy objects" },
{ Py_tp_base, &NoddyType },
{ Py_tp_new, BrownNoddy_new },
{ 0 },
};
PyType_Spec spec = { "noddy.BrownNoddy", sizeof(BrownNoddy), 0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, slots };
PyTypeObject *BrownNoddyType = (PyTypeObject *)PyType_FromSpec(&spec);
Это должно делать все в исходном коде, включая вызов PyType_Ready
, плюс все, что необходимо для создания динамического типа, включая установку Py_TPFLAGS_HEAPTYPE
, а также выделение и инициализацию дополнительной памяти для PyHeapTypeObject
.
Надеюсь, это полезно.