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): """ Callback specification. ffi_cif - something ffi specific, don't care ll_args - rffi.VOIDPP - pointer to array of pointers to args ll_restype - rffi.VOIDP - pointer to result ll_userdata - a special structure which holds necessary information (what the real callback is for example), casted to VOIDP """ e = cerrno.get_real_errno() ll_res = rffi.cast(rffi.CCHARP, ll_res) unique_id = rffi.cast(lltype.Signed, ll_userdata) callback = global_callback_mapping.get(unique_id) if callback is None: # oups! try: os.write(STDERR, "SystemError: invoking a callback " "that was already freed\n") except OSError: 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) return # must_leave = False ec = None space = callback.space try: must_leave = space.threadlocals.try_enter_thread(space) ec = cerrno.get_errno_container(space) cerrno.save_errno_into(ec, e) extra_line = '' try: w_res = callback.invoke(ll_args) extra_line = "Trying to convert the result back to C:\n" callback.convert_result(ll_res, w_res) except OperationError, e: # got an app-level exception callback.print_error(e, extra_line) callback.write_error_return_value(ll_res) # except Exception, e: # oups! last-level attempt to recover. try: os.write(STDERR, "SystemError: callback raised ") os.write(STDERR, str(e)) os.write(STDERR, "\n") except OSError: pass callback.write_error_return_value(ll_res)
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_restype - rffi.VOIDP - pointer to result ll_userdata - a special structure which holds necessary information (what the real callback is for example), casted to VOIDP """ ll_res = rffi.cast(rffi.CCHARP, ll_res) unique_id = rffi.cast(lltype.Signed, ll_userdata) callback = global_callback_mapping.get(unique_id) if callback is None: # oups! try: os.write( STDERR, "SystemError: invoking a callback " "that was already freed\n") except OSError: 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) return # must_leave = False space = callback.space try: must_leave = space.threadlocals.try_enter_thread(space) extra_line = '' try: w_res = callback.invoke(ll_args) extra_line = "Trying to convert the result back to C:\n" callback.convert_result(ll_res, w_res) except OperationError, e: # got an app-level exception callback.print_error(e, extra_line) callback.write_error_return_value(ll_res) # except Exception, e: # oups! last-level attempt to recover. try: os.write(STDERR, "SystemError: callback raised ") os.write(STDERR, str(e)) os.write(STDERR, "\n") except OSError: pass callback.write_error_return_value(ll_res)
def convert_from_object_fficallback(fresult, ll_res, w_res, encode_result_for_libffi): space = fresult.space if isinstance(fresult, W_CTypeVoid): if not space.is_w(w_res, space.w_None): raise oefmt( space.w_TypeError, "callback with the return type 'void' must return " "None") return # small_result = encode_result_for_libffi and fresult.size < SIZE_OF_FFI_ARG if small_result and fresult.is_primitive_integer: # work work work around a libffi irregularity: for integer return # types we have to fill at least a complete 'ffi_arg'-sized result # buffer. if type(fresult) is W_CTypePrimitiveSigned: # It's probably fine to always zero-extend, but you never # know: maybe some code somewhere expects a negative # 'short' result to be returned into EAX as a 32-bit # negative number. Better safe than sorry. This code # is about that case. Let's ignore this for enums. # # do a first conversion only to detect overflows. This # conversion produces stuff that is otherwise ignored. fresult.convert_from_object(ll_res, w_res) # # manual inlining and tweaking of # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- # endian machines) correct the 'result' pointer to write to misc._raw_memclear(ll_res, SIZE_OF_FFI_ARG) if BIG_ENDIAN: diff = SIZE_OF_FFI_ARG - fresult.size ll_res = rffi.ptradd(ll_res, diff) # fresult.convert_from_object(ll_res, w_res)
def convert_from_object_fficallback(fresult, ll_res, w_res, encode_result_for_libffi): space = fresult.space if isinstance(fresult, W_CTypeVoid): if not space.is_w(w_res, space.w_None): raise oefmt(space.w_TypeError, "callback with the return type 'void' must return " "None") return # small_result = encode_result_for_libffi and fresult.size < SIZE_OF_FFI_ARG if small_result and fresult.is_primitive_integer: # work work work around a libffi irregularity: for integer return # types we have to fill at least a complete 'ffi_arg'-sized result # buffer. if type(fresult) is W_CTypePrimitiveSigned: # It's probably fine to always zero-extend, but you never # know: maybe some code somewhere expects a negative # 'short' result to be returned into EAX as a 32-bit # negative number. Better safe than sorry. This code # is about that case. Let's ignore this for enums. # # do a first conversion only to detect overflows. This # conversion produces stuff that is otherwise ignored. fresult.convert_from_object(ll_res, w_res) # # manual inlining and tweaking of # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- # endian machines) correct the 'result' pointer to write to misc._raw_memclear(ll_res, SIZE_OF_FFI_ARG) if BIG_ENDIAN: diff = SIZE_OF_FFI_ARG - fresult.size ll_res = rffi.ptradd(ll_res, diff) # fresult.convert_from_object(ll_res, w_res)
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)