[英]Python object not fully initialized using C API
In the following scenario, the object is not meant to be instantiated within Python (hence no tp_new
or tp_init
).在以下场景中,对象不打算在 Python 中实例化(因此没有
tp_new
或tp_init
)。 Calling the ThingType as a function using PyObject_CallObject
results in a segfault in _PyObject_FastCallDict
, I believe because there are no constructors.使用
PyObject_CallObject
将 ThingType 作为函数调用会导致 _PyObject_FastCallDict 中的段_PyObject_FastCallDict
,我相信是因为没有构造函数。
After creating the object using CreatePythonThing, the function get_height
is not set unless a workaround is applied - to call dir(thing)
, which as a side effect initializes the object's properties.使用 CreatePythonThing 创建对象后,除非应用变通方法 - 调用
dir(thing)
,否则不会设置函数get_height
,这作为初始化对象的属性的副作用。 The workaround is already present in CreatePythonThing
.该解决方法已存在于
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;
}
As in DavidW's comment, I was missing PyType_Ready(&ThingType);
就像 DavidW 的评论一样,我错过了
PyType_Ready(&ThingType);
in my global initializer.在我的全局初始化程序中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.