def get_primitive_type(ffi, num): space = ffi.space if not (0 <= num < cffi_opcode._NUM_PRIM): if num == cffi_opcode._UNKNOWN_PRIM: raise oefmt(ffi.w_FFIError, "primitive integer type with an " "unexpected size (or not an integer type at all)") elif num == cffi_opcode._UNKNOWN_FLOAT_PRIM: raise oefmt(ffi.w_FFIError, "primitive floating-point type with an " "unexpected size (or not a float type at all)") elif num == cffi_opcode._UNKNOWN_LONG_DOUBLE: raise oefmt(ffi.w_FFIError, "primitive floating-point type is " "'long double', not supported for now with " "the syntax 'typedef double... xxx;'") else: raise oefmt(space.w_NotImplementedError, "prim=%d", num) realize_cache = space.fromcache(RealizeCache) w_ctype = realize_cache.all_primitives[num] if w_ctype is None: if num == cffi_opcode.PRIM_VOID: w_ctype = newtype.new_void_type(space) else: assert RealizeCache.NAMES[num] w_ctype = newtype.new_primitive_type(space, RealizeCache.NAMES[num]) realize_cache.all_primitives[num] = w_ctype return w_ctype
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 get_primitive_type(ffi, num): space = ffi.space if not (0 <= num < cffi_opcode._NUM_PRIM): if num == cffi_opcode._UNKNOWN_PRIM: raise oefmt(ffi.w_FFIError, "primitive integer type with an " "unexpected size (or not an integer type at all)") else: raise oefmt(space.w_NotImplementedError, "prim=%d", num) realize_cache = space.fromcache(RealizeCache) w_ctype = realize_cache.all_primitives[num] if w_ctype is None: if num == cffi_opcode.PRIM_VOID: w_ctype = newtype.new_void_type(space) else: assert RealizeCache.NAMES[num] w_ctype = newtype.new_primitive_type(space, RealizeCache.NAMES[num]) realize_cache.all_primitives[num] = w_ctype return w_ctype
def __init__(self, space): self.library = None self.capi_calls = {} import pypy.module._cffi_backend.newtype as nt # TODO: the following need to match up with the globally defined C_XYZ low-level # types (see capi/__init__.py), but by using strings here, that isn't guaranteed c_opaque_ptr = nt.new_primitive_type(space, 'unsigned long') c_scope = c_opaque_ptr c_type = c_scope c_object = c_opaque_ptr c_method = c_opaque_ptr c_index = nt.new_primitive_type(space, 'long') c_void = nt.new_void_type(space) c_char = nt.new_primitive_type(space, 'char') c_uchar = nt.new_primitive_type(space, 'unsigned char') c_short = nt.new_primitive_type(space, 'short') c_int = nt.new_primitive_type(space, 'int') c_long = nt.new_primitive_type(space, 'long') c_llong = nt.new_primitive_type(space, 'long long') c_ullong = nt.new_primitive_type(space, 'unsigned long long') c_float = nt.new_primitive_type(space, 'float') c_double = nt.new_primitive_type(space, 'double') c_ccharp = nt.new_pointer_type(space, c_char) c_index_array = nt.new_pointer_type(space, c_void) c_voidp = nt.new_pointer_type(space, c_void) c_size_t = nt.new_primitive_type(space, 'size_t') c_ptrdiff_t = nt.new_primitive_type(space, 'ptrdiff_t') self.capi_call_ifaces = { # name to opaque C++ scope representation 'num_scopes' : ([c_scope], c_int), 'scope_name' : ([c_scope, c_int], c_ccharp), 'resolve_name' : ([c_ccharp], c_ccharp), 'get_scope' : ([c_ccharp], c_scope), 'get_template' : ([c_ccharp], c_type), 'actual_class' : ([c_type, c_object], c_type), # memory management 'allocate' : ([c_type], c_object), 'deallocate' : ([c_type, c_object], c_void), 'destruct' : ([c_type, c_object], c_void), # method/function dispatching 'call_v' : ([c_method, c_object, c_int, c_voidp], c_void), 'call_b' : ([c_method, c_object, c_int, c_voidp], c_uchar), 'call_c' : ([c_method, c_object, c_int, c_voidp], c_char), 'call_h' : ([c_method, c_object, c_int, c_voidp], c_short), 'call_i' : ([c_method, c_object, c_int, c_voidp], c_int), 'call_l' : ([c_method, c_object, c_int, c_voidp], c_long), 'call_ll' : ([c_method, c_object, c_int, c_voidp], c_llong), 'call_f' : ([c_method, c_object, c_int, c_voidp], c_float), 'call_d' : ([c_method, c_object, c_int, c_voidp], c_double), 'call_r' : ([c_method, c_object, c_int, c_voidp], c_voidp), 'call_s' : ([c_method, c_object, c_int, c_voidp], c_ccharp), 'constructor' : ([c_method, c_object, c_int, c_voidp], c_object), 'call_o' : ([c_method, c_object, c_int, c_voidp, c_type], c_object), 'get_methptr_getter' : ([c_scope, c_index], c_voidp), # TODO: verify # handling of function argument buffer 'allocate_function_args' : ([c_int], c_voidp), 'deallocate_function_args' : ([c_voidp], c_void), 'function_arg_sizeof' : ([], c_size_t), 'function_arg_typeoffset' : ([], c_size_t), # scope reflection information 'is_namespace' : ([c_scope], c_int), 'is_enum' : ([c_ccharp], c_int), # type/class reflection information 'final_name' : ([c_type], c_ccharp), 'scoped_final_name' : ([c_type], c_ccharp), 'has_complex_hierarchy' : ([c_type], c_int), 'num_bases' : ([c_type], c_int), 'base_name' : ([c_type, c_int], c_ccharp), 'is_subtype' : ([c_type, c_type], c_int), 'base_offset' : ([c_type, c_type, c_object, c_int], c_ptrdiff_t), # method/function reflection information 'num_methods' : ([c_scope], c_int), 'method_index_at' : ([c_scope, c_int], c_index), 'method_indices_from_name' : ([c_scope, c_ccharp], c_index_array), 'method_name' : ([c_scope, c_index], c_ccharp), 'method_result_type' : ([c_scope, c_index], c_ccharp), 'method_num_args' : ([c_scope, c_index], c_int), 'method_req_args' : ([c_scope, c_index], c_int), 'method_arg_type' : ([c_scope, c_index, c_int], c_ccharp), 'method_arg_default' : ([c_scope, c_index, c_int], c_ccharp), 'method_signature' : ([c_scope, c_index], c_ccharp), 'method_is_template' : ([c_scope, c_index], c_int), 'method_num_template_args' : ([c_scope, c_index], c_int), 'method_template_arg_name' : ([c_scope, c_index, c_index], c_ccharp), 'get_method' : ([c_scope, c_index], c_method), 'get_global_operator' : ([c_scope, c_scope, c_scope, c_ccharp], c_index), # method properties 'is_constructor' : ([c_type, c_index], c_int), 'is_staticmethod' : ([c_type, c_index], c_int), # data member reflection information 'num_datamembers' : ([c_scope], c_int), 'datamember_name' : ([c_scope, c_int], c_ccharp), 'datamember_type' : ([c_scope, c_int], c_ccharp), 'datamember_offset' : ([c_scope, c_int], c_ptrdiff_t), 'datamember_index' : ([c_scope, c_ccharp], c_int), # data member properties 'is_publicdata' : ([c_scope, c_int], c_int), 'is_staticdata' : ([c_scope, c_int], c_int), # misc helpers 'strtoll' : ([c_ccharp], c_llong), 'strtoull' : ([c_ccharp], c_ullong), 'free' : ([c_voidp], c_void), 'charp2stdstring' : ([c_ccharp], c_object), 'stdstring2stdstring' : ([c_object], c_object), } # size/offset are backend-specific but fixed after load self.c_sizeof_farg = 0 self.c_offset_farg = 0
def __init__(self, space): self.library = None self.capi_calls = {} import pypy.module._cffi_backend.newtype as nt # TODO: the following need to match up with the globally defined C_XYZ low-level # types (see capi/__init__.py), but by using strings here, that isn't guaranteed c_opaque_ptr = nt.new_primitive_type(space, 'unsigned long') c_scope = c_opaque_ptr c_type = c_scope c_object = c_opaque_ptr c_method = c_opaque_ptr c_index = nt.new_primitive_type(space, 'long') c_void = nt.new_void_type(space) c_char = nt.new_primitive_type(space, 'char') c_uchar = nt.new_primitive_type(space, 'unsigned char') c_short = nt.new_primitive_type(space, 'short') c_int = nt.new_primitive_type(space, 'int') c_long = nt.new_primitive_type(space, 'long') c_llong = nt.new_primitive_type(space, 'long long') c_ullong = nt.new_primitive_type(space, 'unsigned long long') c_float = nt.new_primitive_type(space, 'float') c_double = nt.new_primitive_type(space, 'double') c_ccharp = nt.new_pointer_type(space, c_char) c_index_array = nt.new_pointer_type(space, c_void) c_voidp = nt.new_pointer_type(space, c_void) c_size_t = nt.new_primitive_type(space, 'size_t') c_ptrdiff_t = nt.new_primitive_type(space, 'ptrdiff_t') self.capi_call_ifaces = { # name to opaque C++ scope representation 'num_scopes': ([c_scope], c_int), 'scope_name': ([c_scope, c_int], c_ccharp), 'resolve_name': ([c_ccharp], c_ccharp), 'get_scope': ([c_ccharp], c_scope), 'get_template': ([c_ccharp], c_type), 'actual_class': ([c_type, c_object], c_type), # memory management 'allocate': ([c_type], c_object), 'deallocate': ([c_type, c_object], c_void), 'destruct': ([c_type, c_object], c_void), # method/function dispatching 'call_v': ([c_method, c_object, c_int, c_voidp], c_void), 'call_b': ([c_method, c_object, c_int, c_voidp], c_uchar), 'call_c': ([c_method, c_object, c_int, c_voidp], c_char), 'call_h': ([c_method, c_object, c_int, c_voidp], c_short), 'call_i': ([c_method, c_object, c_int, c_voidp], c_int), 'call_l': ([c_method, c_object, c_int, c_voidp], c_long), 'call_ll': ([c_method, c_object, c_int, c_voidp], c_llong), 'call_f': ([c_method, c_object, c_int, c_voidp], c_float), 'call_d': ([c_method, c_object, c_int, c_voidp], c_double), 'call_r': ([c_method, c_object, c_int, c_voidp], c_voidp), 'call_s': ([c_method, c_object, c_int, c_voidp], c_ccharp), 'constructor': ([c_method, c_object, c_int, c_voidp], c_object), 'call_o': ([c_method, c_object, c_int, c_voidp, c_type], c_object), 'get_methptr_getter': ([c_scope, c_index], c_voidp), # TODO: verify # handling of function argument buffer 'allocate_function_args': ([c_int], c_voidp), 'deallocate_function_args': ([c_voidp], c_void), 'function_arg_sizeof': ([], c_size_t), 'function_arg_typeoffset': ([], c_size_t), # scope reflection information 'is_namespace': ([c_scope], c_int), 'is_enum': ([c_ccharp], c_int), # type/class reflection information 'final_name': ([c_type], c_ccharp), 'scoped_final_name': ([c_type], c_ccharp), 'has_complex_hierarchy': ([c_type], c_int), 'num_bases': ([c_type], c_int), 'base_name': ([c_type, c_int], c_ccharp), 'is_subtype': ([c_type, c_type], c_int), 'base_offset': ([c_type, c_type, c_object, c_int], c_ptrdiff_t), # method/function reflection information 'num_methods': ([c_scope], c_int), 'method_index_at': ([c_scope, c_int], c_index), 'method_indices_from_name': ([c_scope, c_ccharp], c_index_array), 'method_name': ([c_scope, c_index], c_ccharp), 'method_result_type': ([c_scope, c_index], c_ccharp), 'method_num_args': ([c_scope, c_index], c_int), 'method_req_args': ([c_scope, c_index], c_int), 'method_arg_type': ([c_scope, c_index, c_int], c_ccharp), 'method_arg_default': ([c_scope, c_index, c_int], c_ccharp), 'method_signature': ([c_scope, c_index], c_ccharp), 'method_is_template': ([c_scope, c_index], c_int), 'method_num_template_args': ([c_scope, c_index], c_int), 'method_template_arg_name': ([c_scope, c_index, c_index], c_ccharp), 'get_method': ([c_scope, c_index], c_method), 'get_global_operator': ([c_scope, c_scope, c_scope, c_ccharp], c_index), # method properties 'is_constructor': ([c_type, c_index], c_int), 'is_staticmethod': ([c_type, c_index], c_int), # data member reflection information 'num_datamembers': ([c_scope], c_int), 'datamember_name': ([c_scope, c_int], c_ccharp), 'datamember_type': ([c_scope, c_int], c_ccharp), 'datamember_offset': ([c_scope, c_int], c_ptrdiff_t), 'datamember_index': ([c_scope, c_ccharp], c_int), # data member properties 'is_publicdata': ([c_scope, c_int], c_int), 'is_staticdata': ([c_scope, c_int], c_int), # misc helpers 'strtoll': ([c_ccharp], c_llong), 'strtoull': ([c_ccharp], c_ullong), 'free': ([c_voidp], c_void), 'charp2stdstring': ([c_ccharp], c_object), 'stdstring2stdstring': ([c_object], c_object), } # size/offset are backend-specific but fixed after load self.c_sizeof_farg = 0 self.c_offset_farg = 0