未使用C API完全初始化Python对象

问题描述 投票:1回答:1

在以下情况下,该对象无意在Python中实例化(因此没有tp_newtp_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;
}
python c python-c-api
1个回答
0
投票

根据DavidW的评论,我在全局初始化器中缺少PyType_Ready(&ThingType);

© www.soinside.com 2019 - 2024. All rights reserved.