Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
412 views
in Technique[技术] by (71.8m points)

c++ - Multithreading with Python and C api

I have a C++ program that uses the C api to use a Python library of mine. Both the Python library AND the C++ code are multithreaded.

In particular, one thread of the C++ program instantiates a Python object that inherits from threading.Thread. I need all my C++ threads to be able to call methods on that object.

From my very first tries (I naively just instantiate the object from the main thread, then wait some time, then call the method) I noticed that the execution of the Python thread associated with the object just created stops as soon as the execution comes back to the C++ program.

If the execution stays with Python (for example, if I call PyRun_SimpleString("time.sleep(5)");) the execution of the Python thread continues in background and everything works fine until the wait ends and the execution goes back to C++.

I am evidently doing something wrong. What should I do to make both my C++ and Python multithreaded and capable of working with each other nicely? I have no previous experience in the field so please don't assume anything!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A correct order of steps to perform what you are trying to do is:

  • In the main thread:

    1. Initialize Python using Py_Initialize*.
    2. Initialize Python threading support using PyEval_InitThreads().
    3. Start the C++ thread.

At this point, the main thread still holds the GIL.

  • In a C++ thread:
    1. Acquire the GIL using PyGILState_Ensure().
    2. Create a new Python thread object and start it.
    3. Release the GIL using PyGILState_Release().
    4. Sleep, do something useful or exit the thread.

Because the main thread holds the GIL, this thread will be waiting to acquire the GIL. If the main thread calls the Python API it may release the GIL from time to time allowing the Python thread to execute for a little while.

  • Back in the main thread:
    1. Release the GIL, enabling threads to run using PyEval_SaveThread()
    2. Before attempting to use other Python calls, reacquire the GIL using PyEval_RestoreThread()

I suspect that you are missing the last step - releasing the GIL in the main thread, allowing the Python thread to execute.

I have a small but complete example that does exactly that at this link.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...