[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