0

在 Python 中,定义内部类很简单:

class MyClass(object):

    class MyInnerClass(object):
        pass

...可以按照预期访问内部类,例如通过执行MyClass.MyInnerClass.

我正在尝试使用扩展模块设置类似的东西。通常,将定义的扩展类型添加到模块<modulename>init()函数中的扩展模块对象,代码如下:

/// …
if (PyType_Ready(&BufferModel_Type) < 0)      { return; }

/// Add the BufferModel type object to the module
Py_INCREF(&BufferModel_Type);
PyModule_AddObject(module,
    "Buffer",
    (PyObject*)&BufferModel_Type);

/// …

为了设置内部类,我改变了这种方法来尝试添加 aPyTypeObject*作为 another 的属性PyTypeObject*,如下所示:

/// …
if (PyType_Ready(&ImageBufferModel_Type) < 0) { return; }
if (PyType_Ready(&ImageModel_Type) < 0)       { return; }

/// Add the ImageBufferModel type object to im.Image
Py_INCREF(&ImageBufferModel_Type);
PyObject_SetAttrString((PyObject*)&ImageModel_Type,
    "ImageBuffer",
    (PyObject*)&ImageBufferModel_Type);
PyType_Modified((PyTypeObject*)&ImageModel_Type);

/// Add the ImageModel type object to the module
Py_INCREF(&ImageModel_Type);
PyModule_AddObject(module,
    "Image",
    (PyObject*)&ImageModel_Type);

/// …

......我认为PyObject_SetAttrString()可以作为C-API 文档中“类型对象”的介绍特别说明:

可以使用任何PyObject_*()PyType_*()函数来处理类型对象 […]

…我PyType_Modified()根据文档中的描述添加了调用。但是这样:当我编译所有内容并尝试加载扩展时,我收到了这个错误:

>>> import im
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    import im
  File "im/__init__.py", line 2, in <module>
    from im import (
TypeError: can't set attributes of built-in/extension type 'im.Image'

……我想我的做法是错误的;我应该尝试什么?

4

1 回答 1

3

为此,您需要tp_dict直接使用:

该字段在被调用之前通常应该被初始化为NULLPyType_Ready;它也可以初始化为包含该类型初始属性的字典。一旦PyType_Ready()初始化了类型,只有当它们不对应于重载操作(如__add__())时,才能将类型的额外属性添加到此字典中。

而不是使用PyObject_SetAttrString()你可以做

PyDict_SetItemString(ImageModel_Type.tp_dict, "ImageBuffer", (PyObject*) &ImageModel_Type);

但在这种情况下,文档中的警告适用:

在字典 C-APIPyDict_SetItem()上使用或以其他方式修改是不安全的。tp_dict

所以也许tp_dict在调用之前PyType_Ready初始化ImageModel_Type

/// Initialize tp_dict with empty dictionary
ImageModel_Type.tp_dict = PyDict_New();
if (!ImageModel_Type.tp_dict) { return; }

/// Add the ImageBufferModel type object to im.Image
if (PyType_Ready(&ImageBufferModel_Type) < 0) { return; }
Py_INCREF(&ImageBufferModel_Type);
PyDict_SetItemString(ImageModel_Type.tp_dict,
    "ImageBuffer",
    (PyObject*)&ImageBufferModel_Type);

/// Add the ImageModel type object to the module
if (PyType_Ready(&ImageModel_Type) < 0) { return; }
Py_INCREF(&ImageModel_Type);
PyModule_AddObject(module,
    "Image",
    (PyObject*)&ImageModel_Type);
于 2016-03-23T00:40:02.637 回答