def prepare_nostruct_fnptr(self, ffi): # tweaked version: instead of returning the ctfuncptr # corresponding exactly to the OP_FUNCTION ... OP_FUNCTION_END # opcodes, this builds in self.nostruct_ctype another one in # which the struct args are replaced with ptr-to- struct, and # a struct return value is replaced with a hidden first arg of # type ptr-to-struct. This is how recompiler.py produces # trampoline functions for PyPy. if self.nostruct_ctype is None: fargs, fret, ellipsis, abi = self._unpack(ffi) # 'locs' will be a string of the same length as the final fargs, # containing 'A' where a struct argument was detected, and 'R' # in first position if a struct return value was detected locs = ['\x00'] * len(fargs) for i in range(len(fargs)): farg = fargs[i] if isinstance(farg, ctypestruct.W_CTypeStructOrUnion): farg = newtype.new_pointer_type(ffi.space, farg) fargs[i] = farg locs[i] = 'A' if isinstance(fret, ctypestruct.W_CTypeStructOrUnion): fret = newtype.new_pointer_type(ffi.space, fret) fargs = [fret] + fargs locs = ['R'] + locs fret = newtype.new_void_type(ffi.space) ctfuncptr = newtype._new_function_type( ffi.space, fargs, fret, ellipsis, abi) if locs == ['\x00'] * len(locs): locs = None else: locs = ''.join(locs) self.nostruct_ctype = ctfuncptr self.nostruct_locs = locs self.nostruct_nargs = len(ctfuncptr.fargs) - (locs is not None and locs[0] == 'R')
def unwrap_as_fnptr(self, ffi): if self._ctfuncptr is None: fargs, fret, ellipsis, abi = self._unpack(ffi) self._ctfuncptr = newtype._new_function_type( ffi.space, fargs, fret, ellipsis, abi) return self._ctfuncptr