Как динамически создавать производный тип в Python C-API

Предположим, у нас есть тип Noddy , как определено в учебнике по написанию модулей расширения C для Python . Теперь мы хотим создать производный тип, перезаписав только метод __ new __ () из Noddy .

В настоящее время я использую следующий подход (проверка ошибок исключена для удобства чтения):

PyTypeObject *BrownNoddyType =
    (PyTypeObject *)PyType_Type.tp_alloc(&PyType_Type, 0);
BrownNoddyType->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
BrownNoddyType->tp_name = "noddy.BrownNoddy";
BrownNoddyType->tp_doc = "BrownNoddy objects";
BrownNoddyType->tp_base = &NoddyType;
BrownNoddyType->tp_new = BrownNoddy_new;
PyType_Ready(BrownNoddyType);

Это работает, но я не уверен, что это правильный способ. Я ожидал, что мне придется установить флаг Py_TPFLAGS_HEAPTYPE , потому что я динамически выделяю объект типа в куче, но это приводит к сбою сегментации в интерпретаторе.

Я также думал о явном вызове type () с использованием PyObject_Call () или подобного, но я отказался от этой идеи. Мне нужно было бы обернуть функцию BrownNoddy_new () в объект функции Python и создать сопоставление словаря __ new __ этому объекту функции, что кажется глупым.

Как лучше всего это сделать? Мой подход правильный? Есть ли функция интерфейса, которую я пропустил?

Обновление

В списке рассылки python-dev (1) (2) есть две темы по связанной теме.Из этих потоков и нескольких экспериментов я пришел к выводу, что мне не следует устанавливать Py_TPFLAGS_HEAPTYPE , если тип не выделяется вызовом type () . В этих потоках есть разные рекомендации, лучше ли выделить тип вручную или вызвать type () . Я был бы доволен последним, если бы я знал, какой рекомендуемый способ обернуть функцию C, которая должна идти в слот tp_new . Для обычных методов этот шаг был бы легким - я мог бы просто использовать PyDescr_NewMethod () , чтобы получить подходящий объект-оболочку. Однако я не знаю, как создать такой объект-оболочку для моего метода __ new __ () - возможно, мне нужна недокументированная функция PyCFunction_New () для создания такого объекта-оболочки.

72
задан Sven Marnach 11 January 2012 в 12:09
поделиться