I'm trying to port some Python 2 code to Python 3. In the code there is a module that is initialized in the C part that is later invoked by the python code. However my python code does not see the module that was initialized in C. Here is a simplified example:
#include <Python.h>
#include <stdio.h>
static PyMethodDef BenchMethods[] = {
{NULL, NULL, 0, NULL}
};
int main(int argc, char **argv)
{
PyObject *module;
Py_SetProgramName(argv[0]);
Py_Initialize();
static struct PyModuleDef benchdef = {
PyModuleDef_HEAD_INIT,
"bench",
NULL,
-1,
BenchMethods,
NULL,
NULL,
NULL,
NULL,
};
module = PyModule_Create(&benchdef);
if (module == NULL) {
printf("ERROR!\n");
exit(0);
}
PyRun_SimpleString("import bench");
Py_Finalize();
return 0;
}
However upon compiling and trying to execute it I get an error:
$ gcc -I/path/to/include/python3.9 -o bench_simple.x bench_simple.c -L/path/to/lib -lpython3.9
$ ./bench_simple.x
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'bench'
In Python 2 version the module is initialized via module = Py_InitModule("bench", BenchMethods);
. I ported the code according to the instructions I found here
CodePudding user response:
PyModule_Create()
(when successful) creates a module object. It does not load that object into any interpreter, and the fact that a module object has been created does not automatically put it in any interpreter's module load path. This is why the import bench
in your example program fails.
The Python C API docs give specific instructions, supported by an example, for how an application embedding python can programmatically define a module and have the embedded interpreter load it. In a nutshell, the key is that instead of your application calling PyModule_Create()
directly, it must
- define a module initialization function that makes that call and returns the result, and
- call
PyImport_AppendInittab()
to register that initialization function to the chosen module name, before initializing an interpreter.