假设我们有 为 Python 编写 C 扩展模块的教程中定义的类型 Noddy
。现在我们要创建一个派生类型,只覆盖 Noddy
的 __new__()
方法。
目前我使用以下方法(为了可读性而去除错误检查) :
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。
我还考虑过使用 PyObject_Call()
或类似方法显式调用 type()
,但我放弃了这个想法。我需要将函数 BrownNoddy_new()
包装在一个 Python 函数对象中,并创建一个将 __new__
映射到这个函数对象的字典,这看起来很愚蠢。
最好的办法是什么?我的方法正确吗?我是不是漏了什么接口功能?
在 python-dev 邮件列表 (1)(2)中有两个关于相关主题的线程。从这些线程和一些实验中,我推断,除非通过调用 type()
来分配类型,否则我不应该设置 Py_TPFLAGS_HEAPTYPE
。无论是手动分配类型还是调用 type()
,这些线程中都有不同的建议。如果我知道包装应该放在 tp_new
插槽中的 C 函数的推荐方法是什么,我会对后者感到满意。对于常规方法,这一步很简单——我可以只使用 PyDescr_NewMethod()
来获得一个合适的包装器对象。但是,我不知道如何为我的 __new__()
方法创建这样一个包装器对象——也许我需要没有文档说明的函数 PyCFunction_New()
来创建这样一个包装器对象。