def descr_addressof(self, w_arg, args_w): """\ Limited equivalent to the '&' operator in C: 1. ffi.addressof(<cdata 'struct-or-union'>) returns a cdata that is a pointer to this struct or union. 2. ffi.addressof(<cdata>, field-or-index...) returns the address of a field or array item inside the given structure or array, recursively in case of nested structures or arrays. 3. ffi.addressof(<library>, "name") returns the address of the named function or global variable.""" # from pypy.module._cffi_backend.lib_obj import W_LibObject space = self.space if isinstance(w_arg, W_LibObject) and len(args_w) == 1: # case 3 in the docstring return w_arg.address_of_func_or_global_var(space.text_w(args_w[0])) # w_ctype = self.ffi_type(w_arg, ACCEPT_CDATA) if len(args_w) == 0: # case 1 in the docstring if (not isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion) and not isinstance(w_ctype, ctypearray.W_CTypeArray)): raise oefmt(space.w_TypeError, "expected a cdata struct/union/array object") offset = 0 else: # case 2 in the docstring if (not isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion) and not isinstance(w_ctype, ctypearray.W_CTypeArray) and not isinstance(w_ctype, ctypeptr.W_CTypePointer)): raise oefmt( space.w_TypeError, "expected a cdata struct/union/array/pointer object") if len(args_w) == 1: w_ctype, offset = w_ctype.direct_typeoffsetof(args_w[0], False) else: w_ctype, offset = self._more_addressof(args_w, w_ctype) # assert isinstance(w_arg, W_CData) cdata = w_arg.unsafe_escaping_ptr() cdata = rffi.ptradd(cdata, offset) w_ctypeptr = newtype.new_pointer_type(space, w_ctype) return W_CData(space, cdata, w_ctypeptr)
def load_function(self, w_ctype, name): from pypy.module._cffi_backend import ctypeptr, ctypearray self.check_closed() space = self.space # if not isinstance(w_ctype, ctypeptr.W_CTypePtrOrArray): raise oefmt(space.w_TypeError, "function or pointer or array cdata expected, got '%s'", w_ctype.name) # try: cdata = dlsym(self.handle, name) except KeyError: raise oefmt(space.w_AttributeError, "function/symbol '%s' not found in library '%s'", name, self.name) if isinstance(w_ctype, ctypearray.W_CTypeArray) and w_ctype.length < 0: w_ctype = w_ctype.ctptr return W_CData(space, rffi.cast(rffi.CCHARP, cdata), w_ctype)
def load_function(self, w_ctype, name): from pypy.module._cffi_backend import ctypefunc, ctypeptr, ctypevoid space = self.space # ok = False if isinstance(w_ctype, ctypefunc.W_CTypeFunc): ok = True if (isinstance(w_ctype, ctypeptr.W_CTypePointer) and isinstance(w_ctype.ctitem, ctypevoid.W_CTypeVoid)): ok = True if not ok: raise oefmt(space.w_TypeError, "function cdata expected, got '%s'", w_ctype.name) # try: cdata = dlsym(self.handle, name) except KeyError: raise oefmt(space.w_KeyError, "function '%s' not found in library '%s'", name, self.name) return W_CData(space, rffi.cast(rffi.CCHARP, cdata), w_ctype)
def address_of_func_or_global_var(self, varname): # rebuild a string object from 'varname', to do typechecks and # to force a unicode back to a plain string space = self.space w_value = self._get_attr(space.wrap(varname)) if isinstance(w_value, cglob.W_GlobSupport): # regular case: a global variable return w_value.address() # if isinstance(w_value, W_FunctionWrapper): # '&func' returns a regular cdata pointer-to-function if w_value.directfnptr: return W_CData(space, w_value.directfnptr, w_value.ctype) else: return w_value # backward compatibility # if (isinstance(w_value, W_CData) and isinstance(w_value.ctype, W_CTypeFunc)): # '&func' is 'func' in C, for a constant function 'func' return w_value # raise oefmt(space.w_AttributeError, "cannot take the address of the constant '%s'", varname)
def _build_attr(self, attr): index = parse_c_type.search_in_globals(self.ctx, attr) if index < 0: for ffi1, lib1 in self.ffi.included_ffis_libs: if lib1 is not None: try: w_result = lib1._get_attr_elidable(attr) break # found, break out of this loop except KeyError: w_result = lib1._build_attr(attr) if w_result is not None: break # found, break out of this loop else: w_result = ffi1.fetch_int_constant(attr) if w_result is not None: break # found, break out of this loop else: return None # not found at all else: space = self.space g = self.ctx.c_globals[index] op = getop(g.c_type_op) if (op == cffi_opcode.OP_CPYTHON_BLTN_V or op == cffi_opcode.OP_CPYTHON_BLTN_N or op == cffi_opcode.OP_CPYTHON_BLTN_O): # A function w_result = self._build_cpython_func(g, attr) # elif op == cffi_opcode.OP_GLOBAL_VAR: # A global variable of the exact type specified here w_ct = realize_c_type.realize_c_type(self.ffi, self.ctx.c_types, getarg(g.c_type_op)) g_size = rffi.cast(lltype.Signed, g.c_size_or_direct_fn) if g_size != w_ct.size and g_size != 0 and w_ct.size > 0: raise oefmt( self.ffi.w_FFIError, "global variable '%s' should be %d bytes " "according to the cdef, but is actually %d", attr, w_ct.size, g_size) ptr = rffi.cast(rffi.CCHARP, g.c_address) if not ptr: # for dlopen() style ptr = self.cdlopen_fetch(attr) w_result = cglob.W_GlobSupport(space, w_ct, ptr) # elif (op == cffi_opcode.OP_CONSTANT_INT or op == cffi_opcode.OP_ENUM): # A constant integer whose value, in an "unsigned long long", # is obtained by calling the function at g->address w_result = realize_c_type.realize_global_int( self.ffi, g, index) # elif (op == cffi_opcode.OP_CONSTANT or op == cffi_opcode.OP_DLOPEN_CONST): # A constant which is not of integer type w_ct = realize_c_type.realize_c_type(self.ffi, self.ctx.c_types, getarg(g.c_type_op)) fetch_funcptr = rffi.cast(realize_c_type.FUNCPTR_FETCH_CHARP, g.c_address) if w_ct.size <= 0: raise oefmt(space.w_SystemError, "constant has no known size") if not fetch_funcptr: # for dlopen() style assert op == cffi_opcode.OP_DLOPEN_CONST ptr = self.cdlopen_fetch(attr) else: assert op == cffi_opcode.OP_CONSTANT ptr = lltype.malloc(rffi.CCHARP.TO, w_ct.size, flavor='raw') self.ffi._finalizer.free_mems.append(ptr) fetch_funcptr(ptr) w_result = w_ct.convert_to_object(ptr) # elif op == cffi_opcode.OP_DLOPEN_FUNC: # For dlopen(): the function of the given 'name'. We use # dlsym() to get the address of something in the dynamic # library, which we interpret as being exactly a function of # the specified type. ptr = self.cdlopen_fetch(attr) w_ct = realize_c_type.realize_c_type_or_func( self.ffi, self.ctx.c_types, getarg(g.c_type_op)) # must have returned a function type: assert isinstance(w_ct, realize_c_type.W_RawFuncType) w_ctfnptr = w_ct.unwrap_as_fnptr(self.ffi) w_result = W_CData(self.space, ptr, w_ctfnptr) # else: raise oefmt(space.w_NotImplementedError, "in lib_build_attr: op=%d", op) assert w_result is not None self.dict_w[attr] = w_result return w_result
def address(self): w_ctypeptr = newtype.new_pointer_type(self.space, self.w_ctype) return W_CData(self.space, self.fetch_global_var_addr(), w_ctypeptr)