如何使用Python C API从对象的方法访问常量?

时间:2019-05-08 18:26:29

标签: python c constants python-c-api

我对another question作了跟进。这个问题是关于如何访问添加到Python C扩展模块中的常量的。

如果要在此初始化函数中向模块添加常量REDBLUE,请改用该问题和答案:

PyMODINIT_FUNC
PyInit_mymodule(void)
{
    PyObject* module = PyModule_Create(&Module);

    // ...

    PyModule_AddStringConstant(module, "BLUE", "blue");
    PyModule_AddStringConstant(module, "RED", "red");

    return module;
}

然后您可以访问它们,例如从这样的函数中返回它们(请记住,必要时必须增加引用计数):

// Get module dict. This is a borrowed reference.
PyObject* module_dict = PyModule_GetDict(module);

// Get BLUE constant. This is a borrowed reference.
PyObject* BLUE = PyDict_GetItemString(module_dict, "BLUE");

// Get RED constant. This is a borrowed reference.
PyObject* RED = PyDict_GetItemString(module_dict, "RED");

如果您有一个指向模块对象的指针,那么效果很好,在链接的问题中就是这种情况。

我的问题是,如果您没有指向模块对象的指针,该怎么做?例如,如果当前函数是对象的方法,则您拥有的self指针用于该对象,而不是模块(并且我无法找到从该对象获取模块的方法):

static PyObject * Foo_get_color(FooObject *self) {
    // How do I get the module object here?
    PyObject *module_dict = PyModule_GetDict(/* ??? */);

    PyObject *color = NULL;
    if (self->color == RED) {
        color = PyDict_GetItemString(module_dict, "RED");
        Py_INCREF(color);
    } else if (self->color == BLUE) {
        color = PyDict_GetItemString(module_dict, "BLUE");
        Py_INCREF(color);
    }

    return color;
}

1 个答案:

答案 0 :(得分:2)

如果您有模块定义(struct PyModuleDef),则可以仅调用PyState_FindModule。我假设在您的示例中,您的结构被命名为Module,所以它看起来像这样:

PyObject * your_function() {
    PyObject *module = PyState_FindModule(&Module);
    PyObject* module_dict = PyModule_GetDict(module);
    ...
}

FindModule documentation说,您需要按如下所示将模块添加到解释器状态:

PyMODINIT_FUNC
PyInit_mymodule(void)
{
    PyObject* module = PyModule_Create(&Module);
    PyState_AddModule(module, &Module);
    ...