Как получить доступ к константам из методов объектов с помощью Python C API? - PullRequest
2 голосов
/ 08 мая 2019

У меня есть продолжение для другого вопроса .Этот вопрос о том, как получить доступ к константам, добавленным в модуль расширения C. Для Python.

Перефразировать этот вопрос и ответить, если вы добавили константы RED и BLUE в свой модуль в функции инициализации, подобной этой:

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 Ответ

2 голосов
/ 08 мая 2019

Если у вас есть определение модуля (struct PyModuleDef), вы можете просто позвонить PyState_FindModule. Я предполагаю, что ваша структура называется Module, как в вашем примере, поэтому она будет выглядеть так:

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

В документации FindModule сказано, что вам нужно добавить модуль в состояние интерпретатора следующим образом:

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