【问题标题】:Python object not fully initialized using C APIPython 对象未使用 C API 完全初始化
【发布时间】:2020-06-27 21:20:54
【问题描述】:

在以下场景中,该对象不打算在 Python 中实例化(因此没有tp_newtp_init)。使用 PyObject_CallObject 将 ThingType 作为函数调用会导致 _PyObject_FastCallDict 中的段错误,我相信是因为没有构造函数。

使用 CreatePythonThing 创建对象后,除非应用解决方法 - 调用 dir(thing),否则不会设置函数 get_height,这会作为副作用初始化对象的属性。解决方法已在 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;
}

【问题讨论】:

  • 模块初始化函数中是否缺少PyType_Ready? (因为你不显示,所以无法分辨)
  • 是的,就是这样!谢谢!

标签: python c python-c-api


【解决方案1】:

正如 DavidW 的评论,我的全局初始化程序中缺少 PyType_Ready(&amp;ThingType);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-25
    • 2021-09-07
    • 2018-08-05
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多