[英]Coercion from Python not allowed without the GIL
I am trying to call a function from a C++ library defined like this:我正在尝试从定义如下的 C++ 库中调用 function :
int somefunc(float timeout);
I doubled a definition in the pxd
file:我将
pxd
文件中的定义加倍:
int somefunc(float timeout) nogil;
But any attempt to call the function with nogil
leads to the same error when cythonizing the pyx
file:但是任何尝试使用 nogil 调用 function 都会在对
pyx
文件进行nogil
时导致相同的错误:
timeout = 1.0
with nogil:
Q.somefunc(timeout)
Error compiling Cython file:
------------------------------------------------------------
...
int(block), timeout,
)
timeout = 1.0
with nogil:
Q.somefunc(timeout)
^
------------------------------------------------------------
script.pyx:105:23: Coercion from Python not allowed without the GIL
I also tried calling it with a ctype, which causes the same error.我还尝试使用 ctype 调用它,这会导致相同的错误。
timeout = ctypes.c_float(1.0)
with nogil:
Q.somefunc(timeout)
Only using a float literal works.仅使用浮点文字有效。 What is the right way to call this function with an actual Python variable?
使用实际 Python 变量调用此 function 的正确方法是什么?
When you look at the generated code for当您查看生成的代码时
timeout = 1.0
Q.somefunc(timeout)
you will see, that timeout
is PyObject
and __pyx_PyFloat_AsFloat
is called to convert is to cdef-float.你会看到,
timeout
是PyObject
并且__pyx_PyFloat_AsFloat
来转换为 cdef-float。 However during this conversion an exception can be raised and for this the gil is needed - thus the error message.但是,在此转换过程中,可能会引发异常,为此需要 gil - 因此会出现错误消息。
The solution would be to force coercion to float
before the nogil-block:解决方案是强制强制在 nogil-block 之前
float
:
cdef float timeout = 1.0
with nogil:
Q.somefunc(timeout)
now timeout is already cdef-float and no conversion is needed in the nogil-block.现在 timeout 已经是 cdef-float 并且 nogil-block 中不需要转换。
Slightly unrelated: I cannot see the code and what Q
is, but most of the time it is wrong to release gil when letting C/C++ code do the work:有点不相关:我看不到代码和
Q
是什么,但大多数时候在让 C/C++ 代码完成工作时释放 gil 是错误的:
When C/C++ uses openMP for parallelization, holding/not holding GIL doesn't change anything for the C/C++-code (here is an example: https://stackoverflow.com/a/60012137/5769463 ).当 C/C++ 使用 openMP 进行并行化时,持有/不持有 GIL 不会改变 C/C++ 代码的任何内容(这是一个示例: https://stackoverflow.com/a/60012137/5769463 )。
When the thread doesn't hold GIL the other could destroy objects needed for the C/C++-code to work (like Q
or other data)当线程不持有 GIL 时,其他线程可能会破坏 C/C++ 代码工作所需的对象(如
Q
或其他数据)
We can release GIL when working with objects implementing buffer protocol, because buffer protocol (when correctly implemented) locks the buffer and the buffer cannot be destroyed from another Python-Thread.我们可以在处理实现缓冲区协议的对象时释放 GIL,因为缓冲区协议(正确实现时)会锁定缓冲区,并且缓冲区不能从另一个 Python 线程中销毁。 Other Python objects have no such locking built-in.
其他 Python 对象没有这种内置锁定。
But as noted above, it might not apply to your code.但如上所述,它可能不适用于您的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.