def delitem(self, space, i, j): if i < 0: i += self.len if i < 0: i = 0 if j < 0: j += self.len if j < 0: j = 0 if j > self.len: j = self.len if i >= j: return None oldbuffer = self.buffer self.buffer = lltype.malloc( mytype.arraytype, max(self.len - (j - i), 0), flavor='raw', add_memory_pressure=True) if i: rffi.c_memcpy( rffi.cast(rffi.VOIDP, self.buffer), rffi.cast(rffi.VOIDP, oldbuffer), i * mytype.bytes ) if j < self.len: rffi.c_memcpy( rffi.cast(rffi.VOIDP, rffi.ptradd(self.buffer, i)), rffi.cast(rffi.VOIDP, rffi.ptradd(oldbuffer, j)), (self.len - j) * mytype.bytes ) self.len -= j - i self.allocated = self.len if oldbuffer: lltype.free(oldbuffer, flavor='raw')
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 _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, 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 array_getitem(ffitype, width, addr, index, offset): for TYPE, ffitype2 in clibffi.ffitype_map: if ffitype is ffitype2: addr = rffi.ptradd(addr, index * width) addr = rffi.ptradd(addr, offset) return rffi.cast(rffi.CArrayPtr(TYPE), addr)[0] assert False
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 method_put_bytes(self, space, start, string, str_offset, nbytes): with rffi.scoped_view_charp(string) as cstring: rffi.c_memcpy( rffi.ptradd(self.ptr, start), rffi.cast(rffi.VOIDP, rffi.ptradd(cstring, str_offset)), nbytes )
def _do_setslice(self, w_slice, w_value): ctptr, start, length = self._do_getslicearg(w_slice) ctitem = ctptr.ctitem ctitemsize = ctitem.size cdata = rffi.ptradd(self._cdata, start * ctitemsize) # if isinstance(w_value, W_CData): from pypy.module._cffi_backend import ctypearray ctv = w_value.ctype if (isinstance(ctv, ctypearray.W_CTypeArray) and ctv.ctitem is ctitem and w_value.get_array_length() == length): # fast path: copying from exactly the correct type s = w_value._cdata for i in range(ctitemsize * length): cdata[i] = s[i] keepalive_until_here(w_value) return # space = self.space w_iter = space.iter(w_value) for i in range(length): try: w_item = space.next(w_iter) except OperationError, e: if not e.match(space, space.w_StopIteration): raise raise operationerrfmt(space.w_ValueError, "need %d values to unpack, got %d", length, i) ctitem.convert_from_object(cdata, w_item) cdata = rffi.ptradd(cdata, ctitemsize)
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 fake_call_impl_any(cif_description, func_addr, exchange_buffer): ofs = 16 for avalue in unroll_avalues: TYPE = rffi.CArray(lltype.typeOf(avalue)) data = rffi.ptradd(exchange_buffer, ofs) got = rffi.cast(lltype.Ptr(TYPE), data)[0] if lltype.typeOf(avalue) is lltype.SingleFloat: got = float(got) avalue = float(avalue) elif (lltype.typeOf(avalue) is rffi.SIGNEDCHAR or lltype.typeOf(avalue) is rffi.UCHAR): got = intmask(got) avalue = intmask(avalue) assert got == avalue ofs += 16 write_to_ofs = 0 if rvalue is not None: write_rvalue = rvalue if BIG_ENDIAN: if (lltype.typeOf(write_rvalue) is rffi.SIGNEDCHAR or lltype.typeOf(write_rvalue) is rffi.UCHAR): # 'write_rvalue' is an int type smaller than Signed write_to_ofs = rffi.sizeof(rffi.LONG) - 1 else: write_rvalue = 12923 # ignored TYPE = rffi.CArray(lltype.typeOf(write_rvalue)) data = rffi.ptradd(exchange_buffer, ofs) rffi.cast(lltype.Ptr(TYPE), data)[write_to_ofs] = write_rvalue
def force_words(self, start, stop): assert start > 0 and stop > 0 and self.size() >= stop and self.pixelbuffer_words >= stop and stop >= start pixbuf = rffi.ptradd(self.display().get_pixelbuffer(), start) realbuf = rffi.ptradd(self._real_depth_buffer, start) rffi.c_memcpy( rffi.cast(rffi.VOIDP, pixbuf), rffi.cast(rffi.VOIDP, realbuf), (stop - start) * constants.BYTES_PER_WORD) # VOIDP is char*, we want to copy word*
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 copy_pixels(self, pixels, start, stop): offset = start * self.bpp assert offset >= 0 remaining_size = (self.width * self.height * self.bpp) - offset if remaining_size <= 0 or start >= stop: return nbytes = rffi.r_size_t(min((stop - start) * self.bpp, remaining_size)) pixbuf = rffi.ptradd(PIXELVOIDPP[0], offset) surfacebuf = rffi.ptradd(rffi.cast(rffi.VOIDP, pixels), offset) rffi.c_memcpy(pixbuf, surfacebuf, nbytes)
def set_native_value(ptr, val, tp): if tp is Integer._type: pnt = rffi.cast(rffi.LONGP, ptr) pnt[0] = rffi.cast(rffi.LONG, val.int_val()) return rffi.cast(rffi.CCHARP, rffi.ptradd(pnt, rffi.sizeof(rffi.LONG))) if tp is String._type: pnt = rffi.cast(rffi.CCHARPP, ptr) pnt[0] = rffi.str2charp(str(rt.name(val))) return rffi.cast(rffi.CCHARP, rffi.ptradd(pnt, rffi.sizeof(rffi.CCHARP))) assert False
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 get_indices(w_start, w_stop, w_step, length): w_slice = space.newslice(w_start, w_stop, w_step) values = lltype.malloc(Py_ssize_tP.TO, 3, flavor='raw') res = api.PySlice_GetIndices(w_slice, 100, values, rffi.ptradd(values, 1), rffi.ptradd(values, 2)) assert res == 0 rv = values[0], values[1], values[2] lltype.free(values, flavor='raw') return rv
def prep_exb(self, args): if not self._is_inited: self.thaw() exb = lltype.malloc(rffi.CCHARP.TO, self._transfer_size, flavor="raw") offset_p = rffi.ptradd(exb, self._arg0_offset) tokens = [None] * len(args) for x in range(len(self._arg_types)): tokens[x] = self._arg_types[x].ffi_set_value(offset_p, args[x]) offset_p = rffi.ptradd(offset_p, self._arg_types[x].ffi_size()) return exb, tokens
def fake_call_impl_any(cif_description, func_addr, exchange_buffer): # read the args from the buffer data_in = rffi.ptradd(exchange_buffer, 16) n = rffi.cast(ARRAY, data_in)[0] # # logic of the function func_ptr = rffi.cast(lltype.Ptr(FUNC), func_addr) n = func_ptr(n) # # write the result to the buffer data_out = rffi.ptradd(exchange_buffer, 32) rffi.cast(ARRAY, data_out)[0] = n
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 jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer): """ This is the function which actually calls libffi. All the rest if just infrastructure to convince the JIT to pass a typed result box to jit_ffi_save_result """ buffer_array = rffi.cast(rffi.VOIDPP, exchange_buffer) for i in range(cif_description.nargs): data = rffi.ptradd(exchange_buffer, cif_description.exchange_args[i]) buffer_array[i] = data resultdata = rffi.ptradd(exchange_buffer, cif_description.exchange_result) clibffi.c_ffi_call(cif_description.cif, func_addr, rffi.cast(rffi.VOIDP, resultdata), buffer_array)
def setitem(self, index, value): if not isinstance(index, Integer): return Object.setitem(self, index, value) index = index.value ctype = self.ctype if isinstance(ctype, Pointer): ctype = ctype.to if isinstance(ctype, Array): pointer = rffi.ptradd(self.pointer, ctype.ctype.size*index) # TODO: could do length check if length present. return ctype.ctype.store(self.pool, pointer, value) elif isinstance(ctype, Type): pointer = rffi.ptradd(self.pointer, ctype.size*index) return ctype.store(self.pool, pointer, value) return Object.setitem(self, Integer(index), value)
def unpack(ptr, offset, tp): """(unpack ptr offset tp) Reads a value of type tp from offset of ptr.""" affirm(isinstance(ptr, VoidP) or isinstance(ptr, Buffer) or isinstance(ptr, CStruct), u"Type is not unpackable") affirm(isinstance(tp, CType), u"Packing type must be a CType") ptr = rffi.ptradd(ptr.raw_data(), offset.int_val()) return tp.ffi_get_value(ptr)
def decode_float(self, i): from rpython.rlib import rdtoa start = rffi.ptradd(self.ll_chars, i) floatval = rdtoa.dg_strtod(start, self.end_ptr) diff = rffi.cast(rffi.LONG, self.end_ptr[0]) - rffi.cast(rffi.LONG, start) self.pos = i + diff return self.space.wrap(floatval)
def call(self, space, w_self, w_args, w_kw): func_to_call = self.func if self.offset: pto = as_pyobj(space, self.w_objclass) # make ptr the equivalent of this, using the offsets #func_to_call = rffi.cast(rffi.VOIDP, ptr.c_tp_as_number.c_nb_multiply) if pto: cptr = rffi.cast(rffi.CCHARP, pto) for o in self.offset: ptr = rffi.cast(rffi.VOIDPP, rffi.ptradd(cptr, o))[0] cptr = rffi.cast(rffi.CCHARP, ptr) func_to_call = rffi.cast(rffi.VOIDP, cptr) else: # Should never happen, assert to get a traceback assert False, "failed to convert w_type %s to PyObject" % str( self.w_objclass) assert func_to_call if self.wrapper_func is None: assert self.wrapper_func_kwds is not None return self.wrapper_func_kwds(space, w_self, w_args, func_to_call, w_kw) if space.is_true(w_kw): raise oefmt(space.w_TypeError, "wrapper %s doesn't take any keyword arguments", self.method_name) return self.wrapper_func(space, w_self, w_args, func_to_call)
def test_rawfuncptr(self): libm = self.get_libm() pow = libm.getrawpointer('pow', [ffi_type_double, ffi_type_double], ffi_type_double) buffer = lltype.malloc(rffi.DOUBLEP.TO, 3, flavor='raw') buffer[0] = 2.0 buffer[1] = 3.0 buffer[2] = 43.5 pow.call([rffi.cast(rffi.VOIDP, buffer), rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 1))], rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 2))) assert buffer[2] == 8.0 lltype.free(buffer, flavor='raw') del pow del libm assert not ALLOCATED
def rawallocate(self, ctypefunc): space = ctypefunc.space self.space = space # compute the total size needed in the CIF_DESCRIPTION buffer self.nb_bytes = 0 self.bufferp = lltype.nullptr(rffi.CCHARP.TO) self.fb_build() # allocate the buffer if we_are_translated(): rawmem = lltype.malloc(rffi.CCHARP.TO, self.nb_bytes, flavor="raw") rawmem = rffi.cast(CIF_DESCRIPTION_P, rawmem) else: # gross overestimation of the length below, but too bad rawmem = lltype.malloc(CIF_DESCRIPTION_P.TO, self.nb_bytes, flavor="raw") # the buffer is automatically managed from the W_CTypeFunc instance ctypefunc.cif_descr = rawmem # call again fb_build() to really build the libffi data structures self.bufferp = rffi.cast(rffi.CCHARP, rawmem) self.fb_build() assert self.bufferp == rffi.ptradd(rffi.cast(rffi.CCHARP, rawmem), self.nb_bytes) # fill in the 'exchange_*' fields self.fb_build_exchange(rawmem) # fill in the extra fields self.fb_extra_fields(rawmem) # call libffi's ffi_prep_cif() function res = jit_libffi.jit_ffi_prep_cif(rawmem) if res != clibffi.FFI_OK: raise OperationError(space.w_SystemError, space.wrap("libffi failed to build this function type"))
def _do_call(self, funcsym, ll_args, RESULT): # XXX: check len(args)? ll_result = lltype.nullptr(rffi.VOIDP.TO) if self.restype != types.void: size = adjust_return_size(intmask(self.restype.c_size)) ll_result = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw') ffires = c_ffi_call(self.ll_cif, self.funcsym, rffi.cast(rffi.VOIDP, ll_result), rffi.cast(rffi.VOIDPP, ll_args)) if RESULT is not lltype.Void: TP = lltype.Ptr(rffi.CArray(RESULT)) if types.is_struct(self.restype): assert RESULT == rffi.SIGNED # for structs, we directly return the buffer and transfer the # ownership buf = rffi.cast(TP, ll_result) res = rffi.cast(RESULT, buf) else: if _BIG_ENDIAN and types.getkind(self.restype) in ('i','u'): ptr = ll_result n = rffi.sizeof(lltype.Signed) - self.restype.c_size ptr = rffi.ptradd(ptr, n) res = rffi.cast(TP, ptr)[0] else: res = rffi.cast(TP, ll_result)[0] else: res = None self._free_buffers(ll_result, ll_args) clibffi.check_fficall_result(ffires, self.flags) return res
def __init__(self, space, ctitem, cdata): self.space = space self.ctitem = ctitem self.cdata = cdata length = cdata.get_array_length() self._next = cdata.unsafe_escaping_ptr() self._stop = rffi.ptradd(self._next, length * ctitem.size)
def test_cdll_life_time(self): from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform from rpython.tool.udir import udir c_file = udir.ensure("test_libffi", dir=1).join("xlib.c") c_file.write(py.code.Source(''' long fun(long i) { return i + 42; } ''')) eci = ExternalCompilationInfo(export_symbols=['fun']) lib_name = str(platform.compile([c_file], eci, 'x', standalone=False)) lib = CDLL(lib_name) slong = cast_type_to_ffitype(rffi.LONG) fun = lib.getrawpointer('fun', [slong], slong) del lib # already delete here buffer = lltype.malloc(rffi.LONGP.TO, 2, flavor='raw') buffer[0] = 200 buffer[1] = -1 fun.call([rffi.cast(rffi.VOIDP, buffer)], rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 1))) assert buffer[1] == 242 lltype.free(buffer, flavor='raw') del fun assert not ALLOCATED
def _more(self): chunk = rffi.cast(CLOSURES, alloc(CHUNK)) count = CHUNK//rffi.sizeof(FFI_CLOSUREP.TO) for i in range(count): rffi.cast(rffi.VOIDPP, chunk)[0] = self.free_list self.free_list = rffi.cast(rffi.VOIDP, chunk) chunk = rffi.ptradd(chunk, 1)
def _do_getitem(self, ctype, i): ctitem = ctype.ctitem with self as ptr: return ctitem.convert_to_object( rffi.ptradd(ptr, i * ctitem.size))
def extract_str(bc, off, size): assert off > 0 and size >= 0 return rffi.charpsize2str(rffi.ptradd(bc, off), size)
def array_setitem_T(TYPE, width, addr, index, offset, value): addr = rffi.ptradd(addr, index * width) addr = rffi.ptradd(addr, offset) rffi.cast(rffi.CArrayPtr(TYPE), addr)[0] = value
def get_method(self, space, offset): offset_ptr = rffi.ptradd(rffi.cast(rffi.CCHARP, self.ptr), offset) raise_if_out_of_bounds(space, offset, self.sizeof_memory, sizeof_type) return rw_strategy.read(space, offset_ptr)
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_cppinstance(space, ptr_result, self.cppclass)
def get_ret_val_from_buffer(self, exb): offset_p = rffi.ptradd(exb, jit.promote(self._cd.exchange_result_libffi)) ret_val = self._ret_type.ffi_get_value(offset_p) return ret_val
def direct_readinto(self, w_rwbuffer): rwbuffer = self.space.writebuf_w(w_rwbuffer) stream = self.getstream() size = rwbuffer.getlength() target_address = lltype.nullptr(rffi.CCHARP.TO) fd = -1 target_pos = 0 if size > 64: try: target_address = rwbuffer.get_raw_address() except ValueError: pass else: fd = stream.try_to_find_file_descriptor() if fd < 0 or not target_address: # fall-back MAX_PART = 1024 * 1024 # 1 MB while size > MAX_PART: data = self.direct_read(MAX_PART) output_slice(self.space, rwbuffer, target_pos, data) target_pos += len(data) size -= len(data) if len(data) != MAX_PART: break else: data = self.direct_read(size) output_slice(self.space, rwbuffer, target_pos, data) target_pos += len(data) else: # optimized case: reading more than 64 bytes into a rwbuffer # with a valid raw address self.check_readable() # first "read" the part that is already sitting in buffers, if any initial_size = min(size, stream.count_buffered_bytes()) if initial_size > 0: data = stream.read(initial_size) output_slice(self.space, rwbuffer, target_pos, data) target_pos += len(data) size -= len(data) # then call c_read() to get the rest if size > 0: stream.flush() while True: got = c_read(fd, rffi.ptradd(target_address, target_pos), size) got = rffi.cast(lltype.Signed, got) if got > 0: target_pos += got size -= got if size <= 0: break elif got == 0: break else: err = rposix.get_saved_errno() if err == errno.EINTR: signal_checker(self.space)() continue if is_wouldblock_error(err) and target_pos > 0: break raise OSError(err, "read error") keepalive_until_here(rwbuffer) return self.space.newint(target_pos)
def pack(ptr, offset): affirm( isinstance(ptr, VoidP) or isinstance(ptr, Buffer) or isinstance(ptr, CStruct), u"Type is not unpackable") ptr = rffi.ptradd(ptr.raw_data(), offset.int_val()) return VoidP(ptr)
def next_w(self): result = self._next if result == self._stop: raise OperationError(self.space.w_StopIteration, self.space.w_None) self._next = rffi.ptradd(result, self.ctitem.size) return self.ctitem.convert_to_object(result)
def add(self, cdata, i): p = rffi.ptradd(cdata, i * self.ctitem.size) return cdataobj.W_CData(self.space, p, self.ctptr)
def ffiobj_init(ffi, module_name, version, types, w_globals, w_struct_unions, w_enums, w_typenames, w_includes): space = ffi.space # xxx force ll2ctypes conversion here. This appears to be needed, # otherwise ll2ctypes explodes. I don't want to know :-( rffi.cast(lltype.Signed, ffi.ctxobj) if version == -1 and not types: return if not (cffi1_module.VERSION_MIN <= version <= cffi1_module.VERSION_MAX): raise oefmt( space.w_ImportError, "cffi out-of-line Python module '%s' has unknown version %s", module_name, hex(version)) if types: # unpack a string of 4-byte entries into an array of _cffi_opcode_t n = len(types) // 4 ntypes = allocate_array(ffi, _CFFI_OPCODE_T, n) decoder = StringDecoder(ffi, types) for i in range(n): ntypes[i] = decoder.next_opcode() ffi.ctxobj.ctx.c_types = ntypes rffi.setintfield(ffi.ctxobj.ctx, 'c_num_types', n) ffi.cached_types = [None] * n if w_globals is not None: # unpack a tuple alternating strings and ints, each two together # describing one global_s entry with no specified address or size. # The int is only used with integer constants. globals_w = space.fixedview(w_globals) n = len(globals_w) // 2 size = n * rffi.sizeof(GLOBAL_S) + n * rffi.sizeof(CDL_INTCONST_S) p = allocate(ffi, size) nglobs = rffi.cast(rffi.CArrayPtr(GLOBAL_S), p) p = rffi.ptradd(p, llmemory.raw_malloc_usage(n * rffi.sizeof(GLOBAL_S))) nintconsts = rffi.cast(rffi.CArrayPtr(CDL_INTCONST_S), p) for i in range(n): decoder = StringDecoder(ffi, space.bytes_w(globals_w[i * 2])) nglobs[i].c_type_op = decoder.next_opcode() nglobs[i].c_name = decoder.next_name() op = getop(nglobs[i].c_type_op) if op == cffi_opcode.OP_CONSTANT_INT or op == cffi_opcode.OP_ENUM: w_integer = globals_w[i * 2 + 1] ll_set_cdl_realize_global_int(nglobs[i]) bigint = space.bigint_w(w_integer) ullvalue = bigint.ulonglongmask() rffi.setintfield(nintconsts[i], 'neg', int(bigint.sign <= 0)) rffi.setintfield(nintconsts[i], 'value', ullvalue) ffi.ctxobj.ctx.c_globals = nglobs rffi.setintfield(ffi.ctxobj.ctx, 'c_num_globals', n) if w_struct_unions is not None: # unpack a tuple of struct/unions, each described as a sub-tuple; # the item 0 of each sub-tuple describes the struct/union, and # the items 1..N-1 describe the fields, if any struct_unions_w = space.fixedview(w_struct_unions) n = len(struct_unions_w) nftot = 0 # total number of fields for i in range(n): nftot += space.len_w(struct_unions_w[i]) - 1 nstructs = allocate_array(ffi, STRUCT_UNION_S, n) nfields = allocate_array(ffi, FIELD_S, nftot) nf = 0 for i in range(n): # 'desc' is the tuple of strings (desc_struct, desc_field_1, ..) desc = space.fixedview(struct_unions_w[i]) nf1 = len(desc) - 1 decoder = StringDecoder(ffi, space.bytes_w(desc[0])) rffi.setintfield(nstructs[i], 'c_type_index', decoder.next_4bytes()) flags = decoder.next_4bytes() rffi.setintfield(nstructs[i], 'c_flags', flags) nstructs[i].c_name = decoder.next_name() if flags & (cffi_opcode.F_OPAQUE | cffi_opcode.F_EXTERNAL): rffi.setintfield(nstructs[i], 'c_size', -1) rffi.setintfield(nstructs[i], 'c_alignment', -1) rffi.setintfield(nstructs[i], 'c_first_field_index', -1) rffi.setintfield(nstructs[i], 'c_num_fields', 0) assert nf1 == 0 else: rffi.setintfield(nstructs[i], 'c_size', -2) rffi.setintfield(nstructs[i], 'c_alignment', -2) rffi.setintfield(nstructs[i], 'c_first_field_index', nf) rffi.setintfield(nstructs[i], 'c_num_fields', nf1) for j in range(nf1): decoder = StringDecoder(ffi, space.bytes_w(desc[j + 1])) # this 'decoder' is for one of the other strings beyond # the first one, describing one field each type_op = decoder.next_opcode() nfields[nf].c_field_type_op = type_op rffi.setintfield(nfields[nf], 'c_field_offset', -1) if getop(type_op) != cffi_opcode.OP_NOOP: field_size = decoder.next_4bytes() else: field_size = -1 rffi.setintfield(nfields[nf], 'c_field_size', field_size) nfields[nf].c_name = decoder.next_name() nf += 1 assert nf == nftot ffi.ctxobj.ctx.c_struct_unions = nstructs ffi.ctxobj.ctx.c_fields = nfields rffi.setintfield(ffi.ctxobj.ctx, 'c_num_struct_unions', n) if w_enums: # unpack a tuple of strings, each of which describes one enum_s entry enums_w = space.fixedview(w_enums) n = len(enums_w) nenums = allocate_array(ffi, ENUM_S, n) for i in range(n): decoder = StringDecoder(ffi, space.bytes_w(enums_w[i])) rffi.setintfield(nenums[i], 'c_type_index', decoder.next_4bytes()) rffi.setintfield(nenums[i], 'c_type_prim', decoder.next_4bytes()) nenums[i].c_name = decoder.next_name() nenums[i].c_enumerators = decoder.next_name() ffi.ctxobj.ctx.c_enums = nenums rffi.setintfield(ffi.ctxobj.ctx, 'c_num_enums', n) if w_typenames: # unpack a tuple of strings, each of which describes one typename_s # entry typenames_w = space.fixedview(w_typenames) n = len(typenames_w) ntypenames = allocate_array(ffi, TYPENAME_S, n) for i in range(n): decoder = StringDecoder(ffi, space.bytes_w(typenames_w[i])) rffi.setintfield(ntypenames[i], 'c_type_index', decoder.next_4bytes()) ntypenames[i].c_name = decoder.next_name() ffi.ctxobj.ctx.c_typenames = ntypenames rffi.setintfield(ffi.ctxobj.ctx, 'c_num_typenames', n) if w_includes: from pypy.module._cffi_backend.ffi_obj import W_FFIObject # for w_parent_ffi in space.fixedview(w_includes): parent_ffi = space.interp_w(W_FFIObject, w_parent_ffi) ffi.included_ffis_libs.append((parent_ffi, None))
def setslice(self, start, string): raw_cdata = rffi.ptradd(self.raw_cdata, start) copy_string_to_raw(llstr(string), raw_cdata, 0, len(string))
def in_map(m, offset): return rffi.ptradd(m.data, offset)
def put_method(self, space, offset, w_value): offset_ptr = rffi.ptradd(rffi.cast(rffi.CCHARP, self.ptr), offset) raise_if_out_of_bounds(space, offset, self.sizeof_memory, sizeof_type) rw_strategy.write(space, offset_ptr, w_value)
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 getslice(self, start, stop, step, size): if step == 1: return rffi.charpsize2str(rffi.ptradd(self.raw_cdata, start), size) return RawBuffer.getslice(self, start, stop, step, size)
def get_raw_address(self): ba = self.ba p = nonmoving_raw_ptr_for_resizable_list(ba._data) p = rffi.ptradd(p, ba._offset) return p
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 f(p): c(rffi.ptradd(p, 0)) lltype.free(p, flavor='raw')
def _operate(stream, data, flush, max_length, cfunc, while_doing): """Common code for compress() and decompress(). """ # Prepare the input buffer for the stream assert data is not None with rffi.scoped_nonmovingbuffer(data) as inbuf: stream.c_next_in = rffi.cast(Bytefp, inbuf) end_inbuf = rffi.ptradd(stream.c_next_in, len(data)) # Prepare the output buffer with lltype.scoped_alloc(rffi.CCHARP.TO, OUTPUT_BUFFER_SIZE) as outbuf: # Strategy: we call deflate() to get as much output data as fits in # the buffer, then accumulate all output into a StringBuffer # 'result'. result = StringBuilder() while True: avail_in = ptrdiff(end_inbuf, stream.c_next_in) if avail_in > INPUT_BUFFER_MAX: avail_in = INPUT_BUFFER_MAX rffi.setintfield(stream, 'c_avail_in', avail_in) stream.c_next_out = rffi.cast(Bytefp, outbuf) bufsize = OUTPUT_BUFFER_SIZE if max_length < bufsize: if max_length <= 0: err = Z_OK break bufsize = max_length max_length -= bufsize rffi.setintfield(stream, 'c_avail_out', bufsize) err = cfunc(stream, flush) if err == Z_OK or err == Z_STREAM_END: # accumulate data into 'result' avail_out = rffi.cast(lltype.Signed, stream.c_avail_out) result.append_charpsize(outbuf, bufsize - avail_out) # if the output buffer is full, there might be more data # so we need to try again. Otherwise, we're done. if avail_out > 0: break # We're also done if we got a Z_STREAM_END (which should # only occur when flush == Z_FINISH). if err == Z_STREAM_END: break else: continue elif err == Z_BUF_ERROR: avail_out = rffi.cast(lltype.Signed, stream.c_avail_out) # When compressing, we will only get Z_BUF_ERROR if # the output buffer was full but there wasn't more # output when we tried again, so it is not an error # condition. if avail_out == bufsize: break # fallback case: report this error raise RZlibError.fromstream(stream, err, while_doing) # When decompressing, if the compressed stream of data was truncated, # then the zlib simply returns Z_OK and waits for more. If it is # complete it returns Z_STREAM_END. avail_in = ptrdiff(end_inbuf, stream.c_next_in) return (result.build(), err, avail_in)
def array_getitem_T(TYPE, width, addr, index, offset): addr = rffi.ptradd(addr, index * width) addr = rffi.ptradd(addr, offset) return rffi.cast(rffi.CArrayPtr(TYPE), addr)[0]
def buffer_advance(self, n): self.ll_buffer = rffi.ptradd(self.ll_buffer, n)
def get_raw_address(self): from rpython.rtyper.lltypesystem import rffi ptr = self.buffer.get_raw_address() return rffi.ptradd(ptr, self.offset)
def get_raw_address(self): from rpython.rtyper.lltypesystem import rffi offset = self.start * self.parent.getstrides()[0] return rffi.ptradd(self.parent.get_raw_address(), offset)
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 setslice(self, index, s): assert s is not None ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), index) rffi.str2chararray(s, ptr, len(s))
def write_raw_complex_data(self, real, imag): with self as ptr: halfsize = self.ctype.size >> 1 ptr2 = rffi.ptradd(ptr, halfsize) misc.write_raw_float_data(ptr, real, halfsize) misc.write_raw_float_data(ptr2, imag, halfsize)
def getslice(self, start, stop, step, size): assert step == 1 assert stop - start == size ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), start) return rffi.charpsize2str(ptr, size)
def exchange_address(ptr, cif_descr, index): return rffi.ptradd(ptr, cif_descr.exchange_args[index])
def get_item(self, nm): (tp, offset) = self._type.get_desc(nm) ptr = rffi.ptradd(self._buffer, offset) return tp.ffi_load_from(ptr)