def invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata): """ Callback specification. ffi_cif - something ffi specific, don't care ll_args - rffi.VOIDPP - pointer to array of pointers to args ll_res - rffi.VOIDP - pointer to result ll_userdata - a special structure which holds necessary information (what the real callback is for example), casted to VOIDP """ cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) ll_res = rffi.cast(rffi.CCHARP, ll_res) callback = reveal_callback(ll_userdata) if callback is None: # oups! try: os.write( STDERR, "SystemError: invoking a callback " "that was already freed\n") except: pass # In this case, we don't even know how big ll_res is. Let's assume # it is just a 'ffi_arg', and store 0 there. misc._raw_memclear(ll_res, SIZE_OF_FFI_ARG) else: callback.invoke(ll_res, rffi.cast(rffi.CCHARP, ll_args)) cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
def _cffi_call_python(ll_externpy, ll_args): """Invoked by the helpers generated from extern "Python" in the cdef. 'externpy' is a static structure that describes which of the extern "Python" functions is called. It has got fields 'name' and 'type_index' describing the function, and more reserved fields that are initially zero. These reserved fields are set up by ffi.def_extern(), which invokes externpy_deco() below. 'args' is a pointer to an array of 8-byte entries. Each entry contains an argument. If an argument is less than 8 bytes, only the part at the beginning of the entry is initialized. If an argument is 'long double' or a struct/union, then it is passed by reference. 'args' is also used as the place to write the result to (directly, even if more than 8 bytes). In all cases, 'args' is at least 8 bytes in size. """ from pypy.module._cffi_backend.ccallback import reveal_callback from rpython.rlib import rgil rgil.acquire() rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) if not ll_externpy.c_reserved1: # Not initialized! We don't have a space at all. # Write the error to the file descriptor stderr. try: funcname = rffi.charp2str(ll_externpy.c_name) msg = ( 'extern "Python": function %s() called, but no code was ' "attached to it yet with @ffi.def_extern(). " "Returning 0.\n" % (funcname,) ) os.write(STDERR, msg) except: pass for i in range(intmask(ll_externpy.c_size_of_result)): ll_args[i] = "\x00" else: externpython = reveal_callback(ll_externpy.c_reserved1) # the same buffer is used both for passing arguments and # the result value externpython.invoke(ll_args, ll_args) cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) rffi.stackcounter.stacks_counter -= 1 rgil.release()
def _cffi_call_python(ll_externpy, ll_args): """Invoked by the helpers generated from extern "Python" in the cdef. 'externpy' is a static structure that describes which of the extern "Python" functions is called. It has got fields 'name' and 'type_index' describing the function, and more reserved fields that are initially zero. These reserved fields are set up by ffi.def_extern(), which invokes externpy_deco() below. 'args' is a pointer to an array of 8-byte entries. Each entry contains an argument. If an argument is less than 8 bytes, only the part at the beginning of the entry is initialized. If an argument is 'long double' or a struct/union, then it is passed by reference. 'args' is also used as the place to write the result to (directly, even if more than 8 bytes). In all cases, 'args' is at least 8 bytes in size. """ from pypy.module._cffi_backend.ccallback import reveal_callback from rpython.rlib import rgil rgil.acquire() rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) if not ll_externpy.c_reserved1: # Not initialized! We don't have a space at all. # Write the error to the file descriptor stderr. try: funcname = rffi.charp2str(ll_externpy.c_name) msg = ("extern \"Python\": function %s() called, but no code was " "attached to it yet with @ffi.def_extern(). " "Returning 0.\n" % (funcname,)) os.write(STDERR, msg) except: pass for i in range(intmask(ll_externpy.c_size_of_result)): ll_args[i] = '\x00' else: externpython = reveal_callback(ll_externpy.c_reserved1) # the same buffer is used both for passing arguments and # the result value externpython.invoke(ll_args, ll_args) cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) rffi.stackcounter.stacks_counter -= 1 rgil.release()
def invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata): """ Callback specification. ffi_cif - something ffi specific, don't care ll_args - rffi.VOIDPP - pointer to array of pointers to args ll_res - rffi.VOIDP - pointer to result ll_userdata - a special structure which holds necessary information (what the real callback is for example), casted to VOIDP """ cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) ll_res = rffi.cast(rffi.CCHARP, ll_res) callback = reveal_callback(ll_userdata) if callback is None: # oups! try: os.write(STDERR, "SystemError: invoking a callback " "that was already freed\n") except: pass # In this case, we don't even know how big ll_res is. Let's assume # it is just a 'ffi_arg', and store 0 there. misc._raw_memclear(ll_res, SIZE_OF_FFI_ARG) else: callback.invoke(ll_res, rffi.cast(rffi.CCHARP, ll_args)) cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
def invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata): cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) _invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata) cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)