Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从C线程调用Python代码_Python_C_Multithreading_Python 3.x_Cpython - Fatal编程技术网

从C线程调用Python代码

从C线程调用Python代码,python,c,multithreading,python-3.x,cpython,Python,C,Multithreading,Python 3.x,Cpython,在从C(或C++)线程调用Python代码时,我非常困惑如何确保线程安全 这句话的意思似乎是,这样做的惯用成语是: PyGILState_STATE gstate; gstate = PyGILState_Ensure(); /* Perform Python actions here. */ result = CallSomeFunction(); /* evaluate result or handle exception */ /* Release the thread. No Pyt

在从C(或C++)线程调用Python代码时,我非常困惑如何确保线程安全

这句话的意思似乎是,这样做的惯用成语是:

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

/* Perform Python actions here. */
result = CallSomeFunction();
/* evaluate result or handle exception */

/* Release the thread. No Python API allowed beyond this point. */
PyGILState_Release(gstate);
事实上,这似乎也证实了这一点。但一位评论员(享有很高的声誉)却表示了相反的看法。评论员说您应该使用
PyEval\u RestoreThread()
/
PyEval\u SaveThread()

文件似乎证实了这一点:

PyThreadState* PyEval_SaveThread()

Release the global interpreter lock (if it has been created and 
thread support is enabled) and reset the thread state to NULL, 
returning the previous thread state (which is not NULL). If the lock 
has been created, the current thread must have acquired it. (This 
function is available even when thread support is disabled at compile 
time.)

void PyEval_RestoreThread(PyThreadState *tstate)

Acquire the global interpreter lock (if it has been created and thread 
support is enabled) and set the thread state to tstate, which must not 
be NULL. If the lock has been created, the current thread must not have 
acquired it, otherwise deadlock ensues. (This function is available even 
when thread support is disabled at compile time.)
文档对此的描述方式似乎是
PyEval\u RestoreThread()
/
PyEval\u SaveThread()
基本上是一种互斥锁/解锁习惯用法。因此,在从C调用任何Python代码之前,首先需要锁定GIL,然后解锁它

那是哪一个呢?从C调用Python代码时,我应该使用:

PyGILState\u sure()/PyGILState\u Release()

PyEval\u RestoreThread/PyEval\u SaveThread



真正的区别是什么呢?

首先,您几乎不想调用
PyEval\u RestoreThread
/
PyEval\u SaveThread
。相反,您希望调用包装宏
Py\u BEGIN\u ALLOW\u THREADS
/
Py\u END\u ALLOW\u THREADS
。是为这些宏编写的,这就是为什么您找不到它的原因

无论如何,不管怎样,您都不会使用线程函数/宏来获取GIL;当您获得GIL时,您可以使用它们临时释放它

那么,你为什么要这么做?好吧,在简单的情况下你不需要;您只需要
确保
/
发布
。但有时您需要将Python线程状态保留到稍后,但不需要保留GIL(或者甚至明确地不需要保留GIL,以允许其他线程继续运行,从而发出信号)。正如文档所解释的,最常见的原因是执行文件I/O或大量CPU限制计算

最后,您是否希望调用函数而不是宏?是,如果您想访问隐藏的PyThreadState。如果你想不出你想要这个的理由,你可能没有理由