Предположим, у нас есть тип 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 ()
для создания такого объекта-оболочки.