def _invoke(self, args): arity = len(args) tp_arity = len(self._c_fn_type._arg_types) if self._c_fn_type._is_variadic: if arity < tp_arity: runtime_error(u"Wrong number of args to fn: got " + unicode(str(arity)) + u", expected at least " + unicode(str(tp_arity))) else: if arity != tp_arity: runtime_error(u"Wrong number of args to fn: got " + unicode(str(arity)) + u", expected " + unicode(str(tp_arity))) exb, tokens = self.prep_exb(args) cd = jit.promote(self._c_fn_type.get_cd()) #fp = jit.promote(self._f_ptr) jit_ffi_call(cd, self._f_ptr, exb) ret_val = self.get_ret_val_from_buffer(exb) for x in range(len(args)): t = tokens[x] if t is not None: t.finalize_token() lltype.free(exb, flavor="raw") keepalive_until_here(args) return ret_val
def ccall(self, pointer, argv): argc = len(argv) if argc != len(self.argtypes): raise Error(u"ffi call expects %d arguments" % argc) if self.notready: self.prepare_cif() self.notready = False cif = self.cif # String objects need to be converted and stored during the call. # I assume it's not a good idea to just generated some and expect them to # stick around. sbuf = [] # Exchange buffer is built for every call. Filled with arguments that are passed to the function. exc = lltype.malloc(rffi.VOIDP.TO, cif.exchange_size, flavor='raw') try: for i in range(argc): offset = rffi.ptradd(exc, cif.exchange_args[i]) arg = argv[i] arg_t = self.argtypes[i] if isinstance(arg, String) and isinstance(arg_t, Pointer): arg = rffi.str2charp(as_cstring(arg)) sbuf.append(arg) arg_t.store_string(offset, arg) else: arg_t.store(offset, arg) jit_libffi.jit_ffi_call(cif, pointer, exc) val = null if isinstance(self.restype, Type): offset = rffi.ptradd(exc, cif.exchange_result) val = self.restype.load(offset) finally: lltype.free(exc, flavor='raw') for sb in sbuf: lltype.free(sb, flavor='raw') return val
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 jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) 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_cdata = rffi.cast(rffi.CCHARPP, data)[0] lltype.free(raw_cdata, flavor='raw') lltype.free(buffer, flavor='raw') keepalive_until_here(args_w) return w_res
def execute_libffi(self, space, cif_descr, funcaddr, buffer): jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer) result = rffi.ptradd(buffer, cif_descr.exchange_result) from pypy.module._cppyy import interp_cppyy ptr_result = rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, result)[0]) return interp_cppyy.wrap_cppobject(space, ptr_result, self.cppclass)
def ccall(self, pointer, argv): argc = len(argv) if argc != len(self.argtypes): raise unwind( LCallError(len(self.argtypes), len(self.argtypes), False, argc)) if self.notready: self.prepare_cif() self.notready = False cif = self.cif # String objects need to be converted and stored during the call. # Also, there are many things that are better treated like this. pool = Pool() #sbuf = [] # Exchange buffer is built for every call. Filled with arguments that are passed to the function. exc = lltype.malloc(rffi.VOIDP.TO, cif.exchange_size, flavor='raw') try: for i in range(argc): offset = rffi.ptradd(exc, cif.exchange_args[i]) arg = argv[i] arg_t = self.argtypes[i] # TODO: fixme? # array handling is wrong. arg_t.store(pool, offset, arg) jit_libffi.jit_ffi_call(cif, pointer, exc) val = null if isinstance(self.restype, Type): offset = rffi.ptradd(exc, cif.exchange_result) val = self.restype.load(offset, True) finally: lltype.free(exc, flavor='raw') pool.free_noreuse() return val
def test_jit_ffi_call(): cd = lltype.malloc(CIF_DESCRIPTION, 1, flavor='raw') cd.abi = clibffi.FFI_DEFAULT_ABI cd.nargs = 1 cd.rtype = clibffi.cast_type_to_ffitype(rffi.DOUBLE) atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, 1, flavor='raw') atypes[0] = clibffi.cast_type_to_ffitype(rffi.DOUBLE) cd.atypes = atypes cd.exchange_size = 64 # 64 bytes of exchange data cd.exchange_result = 24 cd.exchange_args[0] = 16 # jit_ffi_prep_cif(cd) # assert rffi.sizeof(rffi.DOUBLE) == 8 exb = lltype.malloc(rffi.DOUBLEP.TO, 8, flavor='raw') exb[2] = 1.23 jit_ffi_call(cd, math_sin, rffi.cast(rffi.CCHARP, exb)) res = exb[3] lltype.free(exb, flavor='raw') # lltype.free(atypes, flavor='raw') lltype.free(cd, flavor='raw') # assert res == math.sin(1.23)
def invoke(self, space, ptr, args_w, block=None): self = jit.promote(self) if block is not None: args_w.append(block) nargs = len(args_w) assert nargs == self.cif_descr.nargs # size = self.cif_descr.exchange_size buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args_w)): data = rffi.ptradd(buffer, self.cif_descr.exchange_args[i]) w_obj = args_w[i] self._put_arg(space, data, i, w_obj) #ec = cerrno.get_errno_container(space) #cerrno.restore_errno_from(ec) jit_ffi_call(self.cif_descr, rffi.cast(rffi.VOIDP, ptr), buffer) #e = cerrno.get_real_errno() #cerrno.save_errno_into(ec, e) resultdata = rffi.ptradd(buffer, self.cif_descr.exchange_result) w_res = self._get_result(space, resultdata) finally: lltype.free(buffer, flavor='raw') return w_res
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(self, args): exb = self.prep_exb(args) jit_ffi_call(self._cd, self._f_ptr, exb) ret_val = self.get_ret_val_from_buffer(exb) lltype.free(exb, flavor="raw") return ret_val
def invoke(self, space, ptr, args_w, block=None): self = jit.promote(self) if block is not None: args_w.append(block) nargs = len(args_w) assert nargs == self.cif_descr.nargs # size = self.cif_descr.exchange_size buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args_w)): data = rffi.ptradd(buffer, self.cif_descr.exchange_args[i]) w_obj = args_w[i] self._put_arg(space, data, i, w_obj) # ec = cerrno.get_errno_container(space) # cerrno.restore_errno_from(ec) jit_ffi_call(self.cif_descr, rffi.cast(rffi.VOIDP, ptr), buffer) # e = cerrno.get_real_errno() # cerrno.save_errno_into(ec, e) resultdata = rffi.ptradd(buffer, self.cif_descr.exchange_result) w_res = self._get_result(space, resultdata) finally: lltype.free(buffer, flavor='raw') return w_res
def ccall(self, pointer, argv): argc = len(argv) if argc != len(self.argtypes): raise unwind(LCallError(len(self.argtypes), len(self.argtypes), False, argc)) if self.notready: self.prepare_cif() self.notready = False cif = self.cif # String objects need to be converted and stored during the call. # Also, there are many things that are better treated like this. pool = Pool() #sbuf = [] # Exchange buffer is built for every call. Filled with arguments that are passed to the function. exc = lltype.malloc(rffi.VOIDP.TO, cif.exchange_size, flavor='raw') try: for i in range(argc): offset = rffi.ptradd(exc, cif.exchange_args[i]) arg = argv[i] arg_t = self.argtypes[i] # TODO: fixme arg_t.store(pool, offset, arg) jit_libffi.jit_ffi_call(cif, pointer, exc) val = null if isinstance(self.restype, Type): offset = rffi.ptradd(exc, cif.exchange_result) val = self.restype.load(offset, True) finally: lltype.free(exc, flavor='raw') pool.free_noreuse() return val
def _call(self, funcaddr, args_w): space = self.space cif_descr = self.cif_descr # 'self' should have been promoted here 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 jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) 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_cdata = rffi.cast(rffi.CCHARPP, data)[0] lltype.free(raw_cdata, flavor='raw') lltype.free(buffer, flavor='raw') keepalive_until_here(args_w) return w_res
def rcall(self, funcaddr, args): assert self.cif_descr self = jit.promote(self) # no checking of len(args) needed, as calls in this context are not dynamic # The following code is functionally similar to W_CTypeFunc._call, but its # implementation is tailored to the restricted use (include memory handling) # of the CAPI calls. space = self.space cif_descr = self.cif_descr size = cif_descr.exchange_size raw_string = rffi.cast(rffi.CCHARP, 0) # only ever have one in the CAPI buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args)): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) obj = args[i] argtype = self.fargs[i] # the following is clumsy, but the data types used as arguments are # very limited, so it'll do for now if obj.tc == 'l': assert isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned) misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size) elif obj.tc == 'h': assert isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned) misc.write_raw_unsigned_data( data, rffi.cast(rffi.ULONG, obj._handle), argtype.size) elif obj.tc == 'p': assert obj._voidp != rffi.cast(rffi.VOIDP, 0) data = rffi.cast(rffi.VOIDPP, data) data[0] = obj._voidp else: # only other use is sring assert obj.tc == 's' n = len(obj._string) assert raw_string == rffi.cast(rffi.CCHARP, 0) # XXX could use rffi.get_nonmovingbuffer_final_null() raw_string = rffi.str2charp(obj._string) data = rffi.cast(rffi.CCHARPP, data) data[0] = raw_string jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) # this wrapping is unnecessary, but the assumption is that given the # immediate unwrapping, the round-trip is removed w_res = self.ctitem.copy_and_convert_to_object(resultdata) finally: if raw_string != rffi.cast(rffi.CCHARP, 0): rffi.free_charp(raw_string) lltype.free(buffer, flavor='raw') return w_res
def _invoke(self, args): exb = lltype.malloc(rffi.CCHARP.TO, self._transfer_size, flavor="raw") offset_p = rffi.ptradd(exb, self._arg0_offset) self.pack_args(offset_p, args, self._arg_types) jit_ffi_call(self._cd, self._f_ptr, exb) offset_p = rffi.ptradd(exb, self._ret_offset) ret_val = get_ret_val(offset_p, self._ret_type) lltype.free(exb, flavor="raw") return ret_val
def do_call(n): func_ptr = llhelper(lltype.Ptr(FUNC), fn) exbuf = lltype.malloc(rffi.CCHARP.TO, 48, flavor='raw', zero=True) data_in = rffi.ptradd(exbuf, 16) rffi.cast(ARRAY, data_in)[0] = n jit_ffi_call(cif_description, func_ptr, exbuf) data_out = rffi.ptradd(exbuf, 32) res = rffi.cast(ARRAY, data_out)[0] lltype.free(exbuf, flavor='raw') return res
def f(): # jit_ffi_prep_cif(cd) # assert rffi.sizeof(rffi.DOUBLE) == 8 exb = lltype.malloc(rffi.DOUBLEP.TO, 8, flavor='raw') exb[2] = 1.23 jit_ffi_call(cd, math_sin, rffi.cast(rffi.CCHARP, exb)) res = exb[3] lltype.free(exb, flavor='raw') # return res
def rcall(self, funcaddr, args): assert self.cif_descr self = jit.promote(self) # no checking of len(args) needed, as calls in this context are not dynamic # The following code is functionally similar to W_CTypeFunc._call, but its # implementation is tailored to the restricted use (include memory handling) # of the CAPI calls. space = self.space cif_descr = self.cif_descr size = cif_descr.exchange_size raw_string = rffi.cast(rffi.CCHARP, 0) # only ever have one in the CAPI buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args)): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) obj = args[i] argtype = self.fargs[i] # the following is clumsy, but the data types used as arguments are # very limited, so it'll do for now if obj.tc == 'l': assert isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned) misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size) elif obj.tc == 'h': assert isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned) misc.write_raw_unsigned_data(data, rffi.cast(rffi.ULONG, obj._handle), argtype.size) elif obj.tc == 'p': assert obj._voidp != rffi.cast(rffi.VOIDP, 0) data = rffi.cast(rffi.VOIDPP, data) data[0] = obj._voidp else: # only other use is sring assert obj.tc == 's' n = len(obj._string) assert raw_string == rffi.cast(rffi.CCHARP, 0) # XXX could use rffi.get_nonmovingbuffer_final_null() raw_string = rffi.str2charp(obj._string) data = rffi.cast(rffi.CCHARPP, data) data[0] = raw_string jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) # this wrapping is unnecessary, but the assumption is that given the # immediate unwrapping, the round-trip is removed w_res = self.ctitem.copy_and_convert_to_object(resultdata) finally: if raw_string != rffi.cast(rffi.CCHARP, 0): rffi.free_charp(raw_string) lltype.free(buffer, flavor='raw') return w_res
def _invoke(self, args): exb, tokens = self.prep_exb(args) jit_ffi_call(self._cd, self._f_ptr, exb) ret_val = self.get_ret_val_from_buffer(exb) for x in range(len(args)): t = tokens[x] if t is not None: t.finalize_token() lltype.free(exb, flavor="raw") return ret_val
def _call(self, funcaddr, args_w): space = self.space cif_descr = self.cif_descr # 'self' should have been promoted here size = cif_descr.exchange_size mustfree_max_plus_1 = 0 buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: keepalives = [None] * len(args_w) # None or strings 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, keepalives, i): # argtype is a pointer type, and w_obj a list/tuple/str mustfree_max_plus_1 = i + 1 jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) 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) raw_cdata = rffi.cast(rffi.CCHARPP, data)[0] if flag == 1: lltype.free(raw_cdata, flavor='raw') elif flag >= 4: value = keepalives[i] assert value is not None rffi.free_nonmovingbuffer(value, raw_cdata, chr(flag)) lltype.free(buffer, flavor='raw') keepalive_until_here(args_w) return w_res
def f(): exbuf = lltype.malloc(rffi.CCHARP.TO, (len(avalues)+2) * 16, flavor='raw', zero=True) ofs = 16 for avalue in unroll_avalues: TYPE = rffi.CArray(lltype.typeOf(avalue)) data = rffi.ptradd(exbuf, ofs) rffi.cast(lltype.Ptr(TYPE), data)[0] = avalue ofs += 16 jit_ffi_call(cif_description, func_addr, exbuf) if rvalue is None: res = 654321 else: TYPE = rffi.CArray(lltype.typeOf(rvalue)) data = rffi.ptradd(exbuf, ofs) res = rffi.cast(lltype.Ptr(TYPE), data)[0] lltype.free(exbuf, flavor='raw') if lltype.typeOf(res) is lltype.SingleFloat: res = float(res) return res
def builtin_ffi_call(ctx): # parameter validation assert len(ctx.params) == 3 and \ ctx.params[0].type == 'str' and \ ctx.params[1].type == 'str' and \ ctx.params[2].type == 'array' # extract parameters libname = ctx.params[0].strvalue symname = ctx.params[1].strvalue args = ctx.params[2].arrayvalue lib = ctx.machine.space.ffi_libs[libname].lib ff = ctx.machine.space.ffi_functions[(libname, symname)] cif = ff.cif func = rdynload.dlsym(lib, rffi.str2charp(symname)) # prepare exchange exc = lltype.malloc(rffi.VOIDP.TO, cif.exchange_size, flavor='raw') # cast ao val to ffi val ptr = exc for i in range(cif.nargs): ptr = rffi.ptradd(exc, cif.exchange_args[i]) _cast_aovalue_to_ffivalue(ctx.machine.space, args[i], ff.atypes[i], ptr) # ffi call jit_libffi.jit_ffi_call(cif, func, exc) # cast ffi val back to ao val ptr = rffi.ptradd(exc, cif.exchange_result) val = _cast_ffivalue_to_aovalue(ctx.machine.space, ptr, ff.rtype) # free exc lltype.free(exc, flavor='raw') # return val ctx.tos.push(val)
def f(i): exbuf = lltype.malloc(rffi.CCHARP.TO, (len(avalues)+2) * 16, flavor='raw') targetptr = rffi.ptradd(exbuf, 16) for avalue in unroll_avalues: TYPE = rffi.CArray(lltype.typeOf(avalue)) if i >= 9: # a guard that can fail pass rffi.cast(lltype.Ptr(TYPE), targetptr)[0] = avalue targetptr = rffi.ptradd(targetptr, 16) jit_ffi_call(cif_description, func_addr, exbuf) if rvalue is None: res = 654321 else: TYPE = rffi.CArray(lltype.typeOf(rvalue)) res = rffi.cast(lltype.Ptr(TYPE), targetptr)[0] lltype.free(exbuf, flavor='raw') if lltype.typeOf(res) is lltype.SingleFloat: res = float(res) return res
def f(i): exbuf = lltype.malloc(rffi.CCHARP.TO, (len(avalues) + 2) * 16, flavor='raw') targetptr = rffi.ptradd(exbuf, 16) for avalue in unroll_avalues: TYPE = rffi.CArray(lltype.typeOf(avalue)) if i >= 9: # a guard that can fail pass rffi.cast(lltype.Ptr(TYPE), targetptr)[0] = avalue targetptr = rffi.ptradd(targetptr, 16) jit_ffi_call(cif_description, func_addr, exbuf) if rvalue is None: res = 654321 else: TYPE = rffi.CArray(lltype.typeOf(rvalue)) res = rffi.cast(lltype.Ptr(TYPE), targetptr)[0] lltype.free(exbuf, flavor='raw') if lltype.typeOf(res) is lltype.SingleFloat: res = float(res) return res
def execute_libffi(self, space, cif_descr, funcaddr, buffer): jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer) return space.w_None
def execute_libffi(self, space, cif_descr, funcaddr, buffer): if hasattr(space, "fake"): raise NotImplementedError jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer) result = rffi.ptradd(buffer, cif_descr.exchange_result) return self.wrap_result(space, rffi.cast(rffi.LONGP, result)[0])
def execute_libffi(self, space, cif_descr, funcaddr, buf): jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf) result = rffi.ptradd(buf, cif_descr.exchange_result) return self._convert2complex( space, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, result)[0]))
def execute_libffi(self, space, cif_descr, funcaddr, buffer): jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer) result = rffi.ptradd(buffer, cif_descr.exchange_result) return self._wrap_object(space, rffi.cast(self.c_ptrtype, result)[0])
def execute_libffi(self, space, cif_descr, funcaddr, buffer): jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer) result = rffi.ptradd(buffer, cif_descr.exchange_result) from pypy.module.cppyy import interp_cppyy ptr_result = rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, result)[0]) return interp_cppyy.wrap_cppobject(space, ptr_result, self.cppclass)
def execute_libffi(self, space, cif_descr, funcaddr, buffer): jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer) presult = rffi.ptradd(buffer, cif_descr.exchange_result) obj = rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, presult)[0]) return self._wrap_result(space, obj)
def rcall(self, funcaddr, args): assert self.cif_descr self = jit.promote(self) # no checking of len(args) needed, as calls in this context are not dynamic # The following code is functionally similar to W_CTypeFunc._call, but its # implementation is tailored to the restricted use (include memory handling) # of the CAPI calls. space = self.space cif_descr = self.cif_descr size = cif_descr.exchange_size raw_string1 = rffi.cast(rffi.CCHARP, 0) raw_string2 = rffi.cast(rffi.CCHARP, 0) # have max two in any CAPI buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args)): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) obj = args[i] argtype = self.fargs[i] # the following is clumsy, but the data types used as arguments are # very limited, so it'll do for now if obj.tc == 'h': misc.write_raw_unsigned_data( data, rffi.cast(rffi.SIZE_T, obj._scope), argtype.size) elif obj.tc == 'm': misc.write_raw_signed_data( data, rffi.cast(rffi.INTPTR_T, obj._method), argtype.size) elif obj.tc == 'o': # additional cast of void* to intptr_t required for 32b (or intmask fails) misc.write_raw_signed_data( data, rffi.cast(rffi.INTPTR_T, rffi.cast(rffi.VOIDP, obj._object)), argtype.size) elif obj.tc == 'u': misc.write_raw_unsigned_data( data, rffi.cast(rffi.SIZE_T, obj._index), argtype.size) elif obj.tc == 'i': misc.write_raw_signed_data(data, rffi.cast(rffi.INT, obj._int), argtype.size) elif obj.tc == 'd': misc.write_raw_float_data( data, rffi.cast(rffi.DOUBLE, obj._double), argtype.size) elif obj.tc == 'p': assert obj._voidp != rffi.cast(rffi.VOIDP, 0) data = rffi.cast(rffi.VOIDPP, data) data[0] = obj._voidp elif obj.tc == 's': n = len(obj._string) data = rffi.cast(rffi.CCHARPP, data) if raw_string1 == rffi.cast(rffi.CCHARP, 0): # XXX could use rffi.get_nonmovingbuffer_final_null() raw_string1 = rffi.str2charp(obj._string) data[0] = raw_string1 else: assert raw_string2 == rffi.cast(rffi.CCHARP, 0) raw_string2 = rffi.str2charp(obj._string) data[0] = raw_string2 else: # only other use is voidp assert obj.tc == 'p' assert obj._voidp != rffi.cast(rffi.VOIDP, 0) data = rffi.cast(rffi.VOIDPP, data) data[0] = obj._voidp jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) # this wrapping is unnecessary, but the assumption is that given the # immediate unwrapping, the round-trip is removed w_res = self.ctitem.copy_and_convert_to_object(resultdata) finally: if raw_string1 != rffi.cast(rffi.CCHARP, 0): rffi.free_charp(raw_string1) if raw_string2 != rffi.cast(rffi.CCHARP, 0): rffi.free_charp(raw_string2) lltype.free(buffer, flavor='raw') return w_res
def execute_libffi(self, space, cif_descr, funcaddr, buf): jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf) result = rffi.ptradd(buf, cif_descr.exchange_result) return self._wrap_reference( space, rffi.cast(self.c_ptrtype, rffi.cast(rffi.VOIDPP, result)[0]))
def execute_libffi(self, space, cif_descr, funcaddr, buf): jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf) vptr = rffi.ptradd(buf, cif_descr.exchange_result) lres = rffi.cast(rffi.LONG, rffi.cast(rffi.LONGP, vptr)[0]) return self._wrap_object(space, lres)