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

标签 python c python-c-api

在下面的场景中,对象不打算在 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;
}

最佳答案

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

关于Python 对象未使用 C API 完全初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60711460/

相关文章:

python - 将 1D 函数扩展到 3 个维度以进行数据窗口

c++ - 与库的 c 绑定(bind)链接

python - python C API 中新自定义类对象的返回列表

c++ - 作为 C++ 类的 Python 解释器

python - 尝试导入 Tensorflow 时出现 ModuleNotFoundError

python - 如何动态装饰类方法,同时又不失去方法绑定(bind)状态?

c++ - 是否可以将 long long 返回值分配给 int64_t 而不会丢失 64 位机器的精度?

c - *++*p 是可接受的语法吗?

python - __slots__ 在 Python 中是如何实现的?

python - 附加列表但错误 'NoneType' 对象没有属性 'append'