C中的Python线程

alw*_*lin 8 c python multithreading

我在C中编写了一个多线程程序.在创建线程之前,通过调用初始化了一个全局python环境Py_Initialize().然后,在每个创建的线程中,共享全局python环境,并且每个线程调用一个python方法,其参数在C中转换.一切正常,直到这里.

当我time.sleep()在加载的python模块中使用时,C程序引发了一个Segmentation Fault.此外,加载的python模块应该加载另一个C lib来继续工作.我写了以下愚蠢的计数器lib来测试它:

# python part, call the counter function
lib = ctypes.cdll.LoadLibrary(libpycount.so)
for i in xrange(10):
    lib.count()
Run Code Online (Sandbox Code Playgroud)
// C part, dummy countings
#include <stdio.h>
int counter = 1;
void
count() {
    printf("counter:%d \n", counter);
    counter++;
}
Run Code Online (Sandbox Code Playgroud)

我想这可能是因为我没有以正确的方式管理复杂的线程创建.我Non-Python created threads在python doc中找到了.

任何想法或建议?

alw*_*lin 4

我的问题已经解决了。您的问题可能更具体,因此我尝试在这里以更通用的方式编写我的解决方案。希望能帮助到你。


- 在主 C 线程中

  • 首先初始化Python环境:
/*define a global variable to store the main python thread state*/
PyThreadState * mainThreadState = NULL;

if(!Py_IsInitialized())
    Py_Initialize();

mainThreadState = = PyThreadState_Get();
Run Code Online (Sandbox Code Playgroud)
  • 然后启动C线程:
pthread_create(pthread_id, NULL, thread_entrance, NULL);
Run Code Online (Sandbox Code Playgroud)



- 在每个线程中,或者我们可以说在 thread_entrance 函数体内

  • 准备环境:
/*get the lock and create new python thread state*/
PyEval_AcquireLock();
PyInterpreterState * mainInterpreterState = mainThreadState->interp;
PyThreadState * myThreadState = PyThreadState_New(mainInterpreterState);
PyEval_ReleaseLock();    /*don't forget to release the lock*/

/*
 * some C manipulations here
 */
Run Code Online (Sandbox Code Playgroud)
  • 将嵌入的 Python 代码放在这里:
/*get the lock and put your C-Python code here*/
PyEval_AcquireLock();
PyThreadState_Swap(myThreadState);    /*swap your python thread state*/

PyEval_CallObject(py_function, py_arguments);
/*or just something like PyRun_SimpleString("print \"hello world\""); for test*/

PyThreadState_Swap(NULL);    /*clean the thread state before leaving*/
PyEval_ReleaseLock();
Run Code Online (Sandbox Code Playgroud)



- 回到主C线程

  • 当每个线程完成其工作时,完成 python 环境
pthread_join(pthread_id, NULL);
PyEval_RestoreThread(mainThreadState);
Py_Finalize();
Run Code Online (Sandbox Code Playgroud)