0

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 calls Py_Initialize and Py_Finalize respectively;
  • B.dll exports a B_func which calls some cython function declared by cdef 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
    }
7
  • Perhaps you link the two DLLs with different runtimes. Link both with Multi-threaded DLL (/MD) settings, or both with Debug Multi-threaded DLL (/MDd) settings. Other settings may or may not work. Commented Nov 18, 2022 at 7:38
  • Oh and there is absolutely no chance I will put your binaries on my computer. Commented Nov 18, 2022 at 7:41
  • Duplicate of stackoverflow.com/questions/70683041/…. importing the Cython module is required Commented Nov 18, 2022 at 7:48
  • @DavidW Hi, DavidW. This is actually done in start_python, please see my edit. Commented Nov 18, 2022 at 8:09
  • Hi, @n.m. I checked the link settings in the CMakeLists.txt and find no problems. I uploaded the source codes without any binaries, link Commented Nov 18, 2022 at 8:20

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.