我有一个嵌入式的python程序,它在c语言的一个线程中运行。
当python解释器切换线程上下文(将控制权交给另一个线程)时,我希望得到通知,以便可以执行某些必要的操作。
看来Py_AddPendingCall
正是我要找的。然而,api文档对这个函数非常简短,我对如何使用Py_AddPendingCall
感到困惑。通过阅读这些文档,我的理解是:
工作线程调用Py_AddPendingCall
并分配处理程序
功能。
当python解释器运行时,它调用handler函数
每当它将控制权交给另一个线程时
处理程序本身在主解释器线程中执行,其中
吉尔获得了
我在google上搜索了一些演示如何使用Py_AddPendingCall
的示例代码,但什么也找不到。我自己想用它根本不行。处理程序从未被调用。
我的工作线程代码:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
const char* PYTHON_CODE =
"while True:\n"
" for i in range(0,10): print(i)\n"
"\n";
int handler(void* arg)
{
printf("Pending Call invoked!\n");
abort();
}
void* worker_thread(void*)
{
PyGILState_STATE state = PyGILState_Ensure();
int res = Py_AddPendingCall(&func, nullptr);
cout << "Result: " << res << endl;
PyRun_SimpleString(CODE);
PyGILState_Release(state);
return 0;
}
int main()
{
Py_Initialize();
PyEval_InitThreads();
PyEval_ReleaseLock();
pthread_t threads[4];
for (int i = 0; i < 4; ++i)
pthread_create(&threads[i], 0, worker_thread, 0);
for (int i = 0; i < 4; ++i) pthread_join(threads[i], 0);
Py_Finalize();
}
在本例中,
worker_thread
在c中作为pthread工作线程被调用。在这个测试中,我运行了4个工作线程,因此应该进行一些上下文切换。这将无限循环,但挂起的调用处理程序永远不会被调用。那么,有人能提供一个最小的工作示例来说明
Py_AddPendingCall
应该如何使用吗? 最佳答案
挂起的调用只在主线程上执行,并且主线程只能在执行python代码时为挂起的调用提供服务。因此,主线程必须运行一个解释器循环,以便为任何挂起的调用提供服务。从Python/ceval.c
:
Py_MakePendingCalls(void)
{
...
/* only service pending calls on main thread */
if (main_thread && PyThread_get_thread_ident() != main_thread)
return 0;
...
}
在嵌入场景中,“主线程”是调用
PyEval_InitThreads
的线程(注意,当您第一次从python代码启动线程时,也会自动调用它)。因为您的主线程位于pthread_join
中,所以它不会执行python代码,因此也不会分派挂起的调用。还需要注意的是,处理程序只在将控件交给主线程时执行——如果控件从一个工作线程转到另一个工作线程,则处理程序不会运行。因此,
Py_MakePendingCalls
可能不是用于此任务的适当接口。