- 将元类定义为
PyType_Type
的子类 (tp_base
)
- 将
__new__
逻辑放置在tp_init
中
- 通过在
PyVarObject_HEAD_INIT
中引用该元类,将其应用于其他类
#include <Python.h>
#include <iostream>
struct foometa {
PyTypeObject head;
};
int foometa_init(foometa *cls, PyObject *args, PyObject *kwargs) {
if (PyType_Type.tp_init((PyObject*)cls, args, kwargs) < 0) {
return -1;
}
std::cerr << "I'm called on class construction time!\n";
return 0;
}
#define DEFERRED_ADDRESS(ADDR) nullptr
static PyTypeObject foometa_type = {
PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
"demo.foometa",
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
DEFERRED_ADDRESS(&PyType_Type),
0,
0,
0,
0,
(initproc)foometa_init,
0,
0
};
PyObject *fooparent_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject* obj = type->tp_alloc(type, 0);
return obj;
}
static PyTypeObject fooparent_type = {
PyVarObject_HEAD_INIT(&foometa_type, 0)
"demo.fooparent",
sizeof(PyObject),
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
fooparent_new
};
int
demo_init(PyObject *m) {
foometa_type.tp_base = &PyType_Type;
if (PyType_Ready(&foometa_type) < 0) {
return -1;
}
if (PyType_Ready(&fooparent_type) < 0) {
return -1;
}
Py_INCREF(&foometa_type);
if (PyModule_AddObject(m, "foometa",
(PyObject *) &foometa_type) < 0)
return -1;
Py_INCREF(&fooparent_type);
if (PyModule_AddObject(m, "fooparent",
(PyObject *) &fooparent_type) < 0)
return -1;
return 0;
}
static PyModuleDef demomodule = {
PyModuleDef_HEAD_INIT,
"demo",
"Example module",
-1,
NULL, NULL, NULL, NULL, NULL
};
PyMODINIT_FUNC
PyInit_demo() {
PyObject* m = PyModule_Create(&demomodule);
if (m == nullptr) return nullptr;
if (demo_init(m) < 0) return nullptr;
return m;
}
完整的可运行示例请参见https://github.com/ezyang/cpython-metaclass
Modules/gcmodule.c:714: handle_weakrefs: Assertion "wr->wr_object == op" failed
。 - Edward Z. Yangtp_init
是__init__
的 C 语言等效版本,而不是__new__
。__new__
的逻辑应该放在tp_new
中。 - user2357112