Beispiel #1
0
    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
Beispiel #2
0
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)