Предположим, что мы имеем тип 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
, потому что я динамически выделяю объект типа в куче, но делаю это приводит к segfault в интерпретаторе.
Я также думал о явном вызове type()
с помощью PyObject_Call()
или аналогичного, но я отбросил эту идею. Мне нужно было бы обернуть функцию BrownNoddy_new()
в объект функции Python и создать сопоставление словаря __new__
с этим функциональным объектом, что кажется глупым.
Каков наилучший способ сделать это? Правильно ли мой подход? Есть ли функция интерфейса, которую я пропустил?
Update
Есть два потока в соответствующем разделе в списке рассылки python-dev (1) (2). Из этих потоков и нескольких экспериментов я выводю, что я не должен устанавливать Py_TPFLAGS_HEAPTYPE
, если тип не назначен вызовом type()
. В этих потоках существуют разные рекомендации: лучше ли назначать тип вручную или вызывать type()
. Я был бы доволен последним, если бы я знал, какой рекомендуемый способ обернуть функцию C, которая должна находиться в слоте tp_new
. Для обычных методов этот шаг был бы простым - я мог бы просто использовать PyDescr_NewMethod()
, чтобы получить подходящий объект-обертку. Я не знаю, как создать такой объект-оболочку для моего метода __new__()
, хотя, может быть, мне нужна недокументированная функция PyCFunction_New()
для создания такого объекта-оболочки.