Как добавить встроенный модуль в API C-Python после инициализации Py?


У меня есть модуль, определенный в моем C-коде следующим образом:

static struct PyModuleDef module_def = {
    PyModuleDef_HEAD_INIT,
    "the_module_name",  /* m_name */
    module_documentation,  /* m_doc */
    //....
};

И функция для его инициализации:

PyMODINIT_FUNC init_the_module(void)
{
    PyObject *mod, *submodule;
    PyObject *sys_modules = PyThreadState_GET()->interp->modules;

    mod = PyModule_Create(&module_def);

    PyModule_AddObject(mod, "some_submodule", (submodule = init_the_submodule()));
    PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
    Py_INCREF(submodule);

    // more submodules..

    return mod;
}

Приложение, в которое я встраиваю python, довольно большое, и я не могу сильно изменить рабочий процесс. В этот момент Py_Initialize уже был вызван, поэтому я не могу вызвать PyImport_ExtendInittabили PyImport_AppendInittab . Как я могу создать и добавить модуль в системные модули? Может быть, я могу манипулировать словарем модулей напрямую? Вот так:

PyObject *modules, *the_module;
modules = PyImport_GetModuleDict();

PyDict_SetItemString(modules, "the_module_name", init_the_module());

the_module = PyDict_GetItemString(modules, "the_module_name"); //this is getting something back
std::cout << PyDict_Size(the_module) << std::endl; // this prints -1
1 2

1 ответ:

Самый простой способ справиться с этим-статически инициализировать статически связанные модули, непосредственно вызывая initspam () после вызова Py_Initialize () или PyMac_Initialize ():

int main(int argc, char **argv)
{
    /* Pass argv[0] to the Python interpreter */
    Py_SetProgramName(argv[0]);

    /* Initialize the Python interpreter.  Required. */
    Py_Initialize();

    /* Add a static module */
    initspam();

Пример можно найти в файле Demo/embed/demo.c в исходном дистрибутиве Python.