I made several Windows shared libraries (dlls) to hide an embed python under the hood.
- A.dll exports two C functions:
start_python
,stop_python
which callsPy_Initialize
andPy_Finalize
respectively; - B.dll exports a
B_func
which calls some cython function declared bycdef public
. - An application loads A.dll and B.dll by
LoadLibrary
and gets these exported functions, then the following codes cause segmentation fault:
A_start_python(); // in A.dll
B_func(); // in B.dll
A_stop_python(); // in A.dll
B_func
will crash due to some NULL pointer access. It looks like the underlying cython function is called without a living python interpreter. Why?
The following works as expected:
B_start_python(); // in B.dll
B_func(); // in B.dll
B_stop_python(); // in B.dll
There are some other problems when I plays with the demo, for example,
{
A_start_python();
A_stop_python();
B_start_python();
B_func(); // segmentation fault
B_stop_python();
}
{
B_start_python();
B_stop_python();
B_start_python();
B_func(); // AttributeError: 'NoneType' object has no attribute 'current_thread'
B_stop_python();
}
{
B_start_python();
B_func();
B_stop_python();
}
{
B_start_python();
B_func(); // AttributeError: 'NoneType' object has no attribute 'current_thread'
B_stop_python();
}
It seems Python cannot be restarted. I found several other related questions, like this. But the behavior is not the same when starting/stopping python in the same dll or not: segmentation fault vs AttributeError
.
This is A Simple yet Full Demo which reproduces these problems. An embed python included, no other dependencies required. Its a CLion project which is managed by a CMakeLists.txt.
This is just the Source Codes without any binaries
Some implementation details:
bool start_python() {
int status = PyImport_AppendInittab("py_funcs", PyInit_py_funcs);
if (status == -1)
return false;
Py_Initialize();
auto m = PyImport_ImportModule("py_funcs");
return bool(m);
}
void stop_python() {
Py_FinalizeEx();
}
void call_py_func() {
std::cout << "To call_py_func. is Python initialized: " << Py_IsInitialized() << std::endl;
py_func(); // cython cdef public function
}