[Pyrex] Python object returns in "with gil" functions?
Sven Berkvens-Matthijsse
sven at pyrex.berkvens.net
Wed Oct 17 17:04:16 CEST 2007
Hello,
In the most recent version of Pyrex (0.9.6.3), if I try to declare a
function as such:
cdef object test_function() with gil:
# This code is executed after the GIL is (re)acquired
blah = "hello"
return blah
This complains that:
test.pyx:1:25: Function with Python return type cannot be declared nogil
I read in the manual that "with gil" functions automatically get the
"nogil" (safe to call without the GIL acquired) attribute in their
signature, so I understand where the "nogil" comes from.
What I don't understand is why it would be a problem to return a
Python object in a function that is safe to call without the GIL being
acquired. If I don't manipulate the object when the GIL is released,
what is the problem? In the example above, the only thing that comes
after the "PyGILState_Release(_save);" C-statement would be
"return __pyx_r;" which is my 'blah' object. But it is not modified in
any way after PyGILState_Release has been called, so what is the
problem?
My use case is the following: I want to call a "with gil" function as
a callback from a C library which I do not have control over. The C
library expects the callback function to return a void *, which it
will pass on through to the caller of the library code. This caller is
a function that I would define in Pyrex as well, as follows:
-------------------------------------------------------------------------
cdef extern from "library.h":
void *library_function_with_callback(void *(*func)())
cdef extern from "gory_support.h":
object void_ptr_to_object_no_incref(void *)
cdef object test_function() with gil:
# This code is executed after the GIL is (re)acquired
blah = "hello"
return blah
cdef call_library():
cdef void *result
cdef object result_as_obj
with nogil:
result = library_function_with_callback(<void *(*)()>test_function)
result_as_obj = void_ptr_to_object_no_incref(result)
-------------------------------------------------------------------------
I know, the void_ptr_to_object_no_incref() is an ugly hack. But what
this enables me to do is catch exceptions that are raised in the
callback test_function in the call_library function. If I change the
signature of the test_function to return a void *, Pyrex will use
__Pyx_WriteUnraisable to dump any exceptions to stderr, and I can't do
anything about it then.
Does anybody have any insights on this, or perhaps on a better way to
accomplish the same?
--
With kind regards,
Sven
More information about the Pyrex
mailing list