在下面的场景中,对象不打算在 Python 中实例化(因此没有 tp_new
或 tp_init
)。使用 PyObject_CallObject
将 ThingType 作为函数调用会导致 _PyObject_FastCallDict
出现段错误,我相信是因为没有构造函数。
在使用 CreatePythonThing 创建对象后,函数 get_height
不会被设置,除非应用变通方法 - 调用 dir(thing)
,作为副作用初始化对象的属性。解决方法已存在于 CreatePythonThing
中。
#include <Python.h>
typedef struct {
PyObject_HEAD
/* Type-specific fields go here. */
Eval *eval;
} Thing;
static PyObject* ThingGetHeight(PyObject* self, PyObject* args)
{
return PyLong_FromLong(1);
}
static PyMethodDef ThingMethods[] = {
{"get_height", ThingGetHeight, METH_NOARGS, "Get thing height"},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static PyTypeObject ThingType = {
PyVarObject_HEAD_INIT(NULL, 0)
"thing.Thing", /* tp_name */
sizeof(Thing), /* 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 */
"Thing", /* tp_doc */
0, 0, 0, 0, 0, 0,
ThingMethods, /* tp_methods */
};
Thing* CreatePythonThing(Eval *eval)
{
Thing* obj = PyObject_New(Thing, &ThingType);
obj->eval = eval;
obj = (Thing*) PyObject_Init((PyObject*) obj, &ThingType);
// I don't understand why, but the above does not fully initialize the object. The method
// table is not set. Calling `dir` on the object causes it to be initialized, so this is
// a workaround.
PyObject_Dir((PyObject*) obj);
return obj;
}
最佳答案
正如 DavidW 的评论,我在我的全局初始化程序中缺少 PyType_Ready(&ThingType);
。
关于Python 对象未使用 C API 完全初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60711460/