如何在Py_Initialize之后将内置模块添加到C-Python API?

时间:2014-06-10 17:13:45

标签: python-c-api

我的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_ExtendInittabPyImport_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 个答案:

答案 0 :(得分:1)

处理此问题的最简单方法是在调用Py_Initialize()或PyMac_Initialize()之后直接调用initspam()来静态初始化静态链接的模块:

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();

可以在Python源代码分发中的Demo / embed / demo.c文件中找到一个示例。