【发布时间】:2017-02-18 21:39:47
【问题描述】:
使用 Python C/API,如何使用普通 Python 类创建机制(即:不是扩展类型)创建普通 Python 类?
换句话说,一个语句的 Python C/API 等价物是什么(在某种意义上它完全在所有情况下都一样)
class X(bases):
...some methods/attributes here...
【问题讨论】:
标签: python class python-c-api
使用 Python C/API,如何使用普通 Python 类创建机制(即:不是扩展类型)创建普通 Python 类?
换句话说,一个语句的 Python C/API 等价物是什么(在某种意义上它完全在所有情况下都一样)
class X(bases):
...some methods/attributes here...
【问题讨论】:
标签: python class python-c-api
在 Python 中,您可以通过调用 type 内置函数以编程方式创建一个类。例如,请参阅this answer。
这需要三个参数:名称、基元组和字典。
您可以在 C api 中以PyType_Type 的形式获取 Python type。然后你只需要使用one of the standard methods for calling PyObject* callables调用它:
// 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* 但它不是!)
【讨论】:
Derived = metaclass("Derived", (Base,), {})。但是,这稍微超出了我的实际确定范围......
PyTypeObjects(但似乎没有人喜欢它......)
我不确定您所说的“正常的 Python 类创建机制”是什么意思,但是...
有一个专门的文档页面:https://docs.python.org/3/extending/newtypes.html——它在扩展模块中创建一个新类型,相当于在 Python 代码中创建一个新的class。
这里给出的最小示例是:
#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;
}
【讨论】: