Reputation: 7188
I am trying to call a function from a C++ library defined like this:
int somefunc(float timeout);
I doubled a definition in the pxd
file:
int somefunc(float timeout) nogil;
But any attempt to call the function with nogil
leads to the same error when cythonizing the pyx
file:
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.
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?
Upvotes: 3
Views: 5635
Reputation: 34347
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. However during this conversion an exception can be raised and for this the gil is needed - thus the error message.
The solution would be to force coercion to float
before the nogil-block:
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.
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:
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).
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)
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. Other Python objects have no such locking built-in.
But as noted above, it might not apply to your code.
Upvotes: 3