Python C / API:如何创建普通类

Python C/API: how to create a normal class

使用python c/api,如何使用普通的python类创建机制(即:不是扩展类型)创建普通的python类?

换句话说,一条语句的python c/api等价物是什么(在所有情况下,它的作用完全相同)

1
2
class X(bases):
    ...some methods/attributes here...


在python中,可以通过调用type内置函数以编程方式创建类。例如,请参阅此答案。

这需要三个参数:一个名称、一个基元组和一个字典。

您可以在C API中获得python type作为PyType_Type。然后,您只需要使用调用PyObject*可调用文件的标准方法之一来调用它:

1
2
3
4
5
6
7
8
9
10
11
12
13
// make a tuple of your bases
PyObject* bases = PyTuple_Pack(0); // assume no bases
// make a dictionary of member functions, etc
PyObject* dict = PyDict_New(); // empty for the sake of example
PyObject* my_new_class = PyObject_CallFunction(&PyType_Type,"sOO",
                                            "X", // class name
                                             bases,
                                             dict);
// check if null

// decref bases and dict
Py_CLEAR(bases);
Py_CLEAR(dict);

(请注意,您必须执行&PyType_Type-文档暗示它是PyObject*,但它不是!)


我不知道你所说的"普通的Python类创建机制"是什么意思,但是…

这里有一个专门的文档页面:https://docs.python.org/3/extending/new type s.html——它在扩展模块中创建了一个新的类型,相当于在python代码中创建了一个新的class

最简单的例子是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <Python.h>

typedef struct {
    PyObject_HEAD
    /* Type-specific fields go here. */
} noddy_NoddyObject;

static PyTypeObject noddy_NoddyType = {
    PyVarObject_HEAD_INIT(NULL, 0)
   "noddy.Noddy",             /* tp_name */
    sizeof(noddy_NoddyObject), /* tp_basicsize */
    0,                         /* tp_itemsize */
    0,                         /* tp_dealloc */
    0,                         /* tp_print */
    0,                         /* tp_getattr */
    0,                         /* tp_setattr */
    0,                         /* tp_reserved */
    0,                         /* tp_repr */
    0,                         /* tp_as_number */
    0,                         /* tp_as_sequence */
    0,                         /* tp_as_mapping */
    0,                         /* tp_hash  */
    0,                         /* tp_call */
    0,                         /* tp_str */
    0,                         /* tp_getattro */
    0,                         /* tp_setattro */
    0,                         /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT,        /* tp_flags */
   "Noddy objects",           /* tp_doc */
};

static PyModuleDef noddymodule = {
    PyModuleDef_HEAD_INIT,
   "noddy",
   "Example module that creates an extension type.",
    -1,
    NULL, NULL, NULL, NULL, NULL
};

PyMODINIT_FUNC
PyInit_noddy(void)
{
    PyObject* m;

    noddy_NoddyType.tp_new = PyType_GenericNew;
    if (PyType_Ready(&noddy_NoddyType) < 0)
        return NULL;

    m = PyModule_Create(&noddymodule);
    if (m == NULL)
        return NULL;

    Py_INCREF(&noddy_NoddyType);
    PyModule_AddObject(m,"Noddy", (PyObject *)&noddy_NoddyType);
    return m;
}