使用Python和C api进行多线程处理

Mat*_*nti 10 c++ python multithreading python-c-api

我有一个C++程序,它使用C api来使用我的Python库. Python库和C++代码都是多线程的.

特别是,C++程序的一个线程实例化一个继承自的Python对象threading.Thread.我需要所有的C++线程能够调用该对象上的方法.

从我第一次尝试(我天真地只是从主线程实例化对象,然后等待一段时间,然后调用方法)我注意到,执行返回后,与刚刚创建的对象关联的Python线程的执行就会停止到C++程序.

如果执行仍然使用Python(例如,如果我调用PyRun_SimpleString("time.sleep(5)");),Python线程的执行将在后台继续执行,一切正常,直到等待结束并执行返回到C++.

我显然做错了什么.我应该怎么做才能让两个我的C++和Python的多线程和能够彼此很好地工作?我以前没有这方面的经验所以请不要假设!

ste*_*rin 11

执行您要执行的操作的正确步骤顺序是:

  • 在主线程中:

    1. 使用初始化Python Py_Initialize*.
    2. 使用初始化Python线程支持PyEval_InitThreads().
    3. 启动C++线程.

此时,主线程仍然保持GIL.

  • 在C++线程中:
    1. 使用获取GIL PyGILState_Ensure().
    2. 创建一个新的Python线程对象并启动它.
    3. 使用释放GIL PyGILState_Release().
    4. 睡觉,做一些有用的事情或退出线程.

因为主线程持有GIL,所以此线程将等待获取GIL.如果主线程调用Python API,它可能会不时释放GIL,允许Python线程执行一段时间.

  • 回到主线程:
    1. 释放GIL,使线程能够运行 PyEval_SaveThread()
    2. 在尝试使用其他Python调用之前,请使用重新获取GIL PyEval_RestoreThread()

我怀疑你错过了最后一步 - 在主线程中释放GIL,允许Python线程执行.

我有一个小但完整的例子,在这个链接上完成了这个.