def _call(self, funcaddr, args_w): space = self.space cif_descr = self.cif_descr size = cif_descr.exchange_size mustfree_max_plus_1 = 0 buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor="raw") try: for i in range(len(args_w)): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) w_obj = args_w[i] argtype = self.fargs[i] if argtype.convert_argument_from_object(data, w_obj): # argtype is a pointer type, and w_obj a list/tuple/str mustfree_max_plus_1 = i + 1 ec = cerrno.get_errno_container(space) cerrno.restore_errno_from(ec) jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) e = cerrno.get_real_errno() cerrno.save_errno_into(ec, e) resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) w_res = self.ctitem.copy_and_convert_to_object(resultdata) finally: for i in range(mustfree_max_plus_1): argtype = self.fargs[i] if isinstance(argtype, W_CTypePointer): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) flag = get_mustfree_flag(data) if flag == 1: raw_string = rffi.cast(rffi.CCHARPP, data)[0] lltype.free(raw_string, flavor="raw") lltype.free(buffer, flavor="raw") return 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_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)