def test_pass_around_t_object(self): from pypy.rpython.annlowlevel import base_ptr_lltype T = base_ptr_lltype() class X(object): _TYPE = T x = 10 def callback(x): return x.x c_source = py.code.Source(""" int eating_callback(void *arg, int(*call)(int)) { return call(arg); } """) eci = ExternalCompilationInfo(separate_module_sources=[c_source], export_symbols=['eating_callback']) args = [T, rffi.CCallback([T], rffi.INT)] eating_callback = rffi.llexternal('eating_callback', args, rffi.INT, compilation_info=eci) res = eating_callback(X(), callback) assert res == 10
def test_pass_around_t_object(self): from pypy.rpython.annlowlevel import base_ptr_lltype T = base_ptr_lltype() class X(object): _TYPE = T x = 10 def callback(x): return x.x c_source = py.code.Source(""" long eating_callback(void *arg, long(*call)(void*)) { return call(arg); } """) eci = ExternalCompilationInfo(separate_module_sources=[c_source], export_symbols=['eating_callback']) args = [T, rffi.CCallback([T], rffi.LONG)] eating_callback = rffi.llexternal('eating_callback', args, rffi.LONG, compilation_info=eci) res = eating_callback(X(), callback) assert res == 10
def test_cast_instance_to_base_ptr(self): class X(object): pass x = X() ptr = annlowlevel.cast_instance_to_base_ptr(x) assert lltype.typeOf(ptr) == annlowlevel.base_ptr_lltype() y = annlowlevel.cast_base_ptr_to_instance(X, ptr) assert y is x
def new_opaque_object(llobj): try: return _opaque_cache[llobj] except KeyError: assert len(_opaque_cache) == len(_opaque_list) ctypes_type = get_ctypes_type(base_ptr_lltype()) val = ctypes.cast(len(_opaque_cache), ctypes_type) _opaque_list.append(llobj) _opaque_cache[llobj] = val return val
def test_cast_instance_to_base_ptr(): class A: def __init__(self, x, y): self.x = x self.y = y def f(x, y): if x > 20: a = None else: a = A(x, y) a1 = cast_instance_to_base_ptr(a) return a1 res = interpret(f, [5, 10]) assert typeOf(res) == base_ptr_lltype() assert fishllattr(res, 'x') == 5 assert fishllattr(res, 'y') == 10 res = interpret(f, [25, 10]) assert res == nullptr(base_ptr_lltype().TO)
def try_cast_gcref_to_instance(Class, gcref): # Before translation, unwraps the RPython instance contained in a _GcRef. # After translation, it is a type-check performed by the GC. if we_are_translated(): from pypy.rpython.annlowlevel import base_ptr_lltype from pypy.rpython.annlowlevel import cast_base_ptr_to_instance from pypy.rpython.lltypesystem import rclass if _is_rpy_instance(gcref): objptr = lltype.cast_opaque_ptr(base_ptr_lltype(), gcref) if objptr.typeptr: # may be NULL, e.g. in rdict's dummykeyobj clsptr = _get_llcls_from_cls(Class) if rclass.ll_isinstance(objptr, clsptr): return cast_base_ptr_to_instance(Class, objptr) return None else: if isinstance(gcref._x, Class): return gcref._x return None
# # class Numbering: __slots__ = ['prev', 'nums'] # # except that it is more compact in translated programs, because the # array 'nums' is inlined in the single NUMBERING object. This is # important because this is often the biggest single consumer of memory # in a pypy-c-jit. # NUMBERINGP = lltype.Ptr(lltype.GcForwardReference()) NUMBERING = lltype.GcStruct('Numbering', ('prev', NUMBERINGP), ('nums', lltype.Array(rffi.SHORT))) NUMBERINGP.TO.become(NUMBERING) PENDINGFIELDSTRUCT = lltype.Struct('PendingField', ('lldescr', annlowlevel.base_ptr_lltype()), ('num', rffi.SHORT), ('fieldnum', rffi.SHORT), ('itemindex', rffi.INT)) PENDINGFIELDSP = lltype.Ptr(lltype.GcArray(PENDINGFIELDSTRUCT)) TAGMASK = 3 def tag(value, tagbits): if tagbits >> 2: raise ValueError sx = value >> 13 if sx != 0 and sx != -1: raise ValueError return rffi.r_short(value<<2|tagbits)
def ctypes2lltype(T, cobj): """Convert the ctypes object 'cobj' to its lltype equivalent. 'T' is the expected lltype type. """ if T is lltype.Void: return None if isinstance(T, lltype.Ptr): if not cobj: # NULL pointer return lltype.nullptr(T.TO) if T is base_ptr_lltype(): return _opaque_list[ctypes.cast(cobj, ctypes.c_void_p).value] if isinstance(T.TO, lltype.Struct): if T.TO._arrayfld is not None: carray = getattr(cobj.contents, T.TO._arrayfld) container = lltype._struct(T.TO, carray.length) else: # special treatment of 'OBJECT' subclasses if get_rtyper() and lltype._castdepth(T.TO, OBJECT) > 0: ctypes_object = get_ctypes_type(lltype.Ptr(OBJECT)) as_obj = ctypes2lltype(lltype.Ptr(OBJECT), ctypes.cast(cobj, ctypes_object)) TObj = get_rtyper().get_type_for_typeptr(as_obj.typeptr) if TObj != T.TO: ctypes_instance = get_ctypes_type(lltype.Ptr(TObj)) return lltype.cast_pointer(T, ctypes2lltype(lltype.Ptr(TObj), ctypes.cast(cobj, ctypes_instance))) container = lltype._struct(T.TO) struct_use_ctypes_storage(container, cobj.contents) elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): container = _array_of_unknown_length(T.TO) container._storage = cobj.contents else: container = _array_of_known_length(T.TO) container._storage = cobj.contents elif isinstance(T.TO, lltype.FuncType): cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value if cobjkey in _callback2obj: container = _callback2obj[cobjkey] else: _callable = get_ctypes_trampoline(T.TO, cobj) return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), _callable=_callable) elif isinstance(T.TO, lltype.OpaqueType): if T == llmemory.GCREF: # XXX obscure hack return _llgcref(cobj) else: container = lltype._opaque(T.TO) else: raise NotImplementedError(T) llobj = lltype._ptr(T, container, solid=True) elif T is llmemory.Address: if cobj is None: llobj = llmemory.NULL else: llobj = _lladdress(cobj) elif T is lltype.Char: llobj = chr(cobj) elif T is lltype.UniChar: llobj = unichr(cobj) elif T is lltype.Signed: llobj = cobj elif T is lltype.SingleFloat: if isinstance(cobj, ctypes.c_float): cobj = cobj.value llobj = r_singlefloat(cobj) elif T is lltype.Void: llobj = cobj else: from pypy.rpython.lltypesystem import rffi try: inttype = rffi.platform.numbertype_to_rclass[T] except KeyError: llobj = cobj else: llobj = inttype(cobj) assert lltype.typeOf(llobj) == T return llobj
def lltype2ctypes(llobj, normalize=True): """Convert the lltype object 'llobj' to its ctypes equivalent. 'normalize' should only be False in tests, where we want to inspect the resulting ctypes object manually. """ if isinstance(llobj, lltype._uninitialized): return uninitialized2ctypes(llobj.TYPE) T = lltype.typeOf(llobj) if isinstance(T, lltype.Ptr): if not llobj: # NULL pointer return get_ctypes_type(T)() if T is base_ptr_lltype(): return new_opaque_object(llobj) if T == llmemory.GCREF: if isinstance(llobj, _llgcref): return ctypes.c_void_p(llobj.intval) container = llobj._obj.container T = lltype.Ptr(lltype.typeOf(container)) # otherwise it came from integer and we want a c_void_p with # the same valu else: container = llobj._obj if isinstance(T.TO, lltype.FuncType): # XXX a temporary workaround for comparison of lltype.FuncType key = llobj._obj.__dict__.copy() key['_TYPE'] = repr(key['_TYPE']) items = key.items() items.sort() key = tuple(items) if key in _all_callbacks: return _all_callbacks[key] v1voidlist = [(i, getattr(container, '_void' + str(i), None)) for i in range(len(T.TO.ARGS)) if T.TO.ARGS[i] is lltype.Void] def callback(*cargs): cargs = list(cargs) for v1 in v1voidlist: cargs.insert(v1[0], v1[1]) assert len(cargs) == len(T.TO.ARGS) llargs = [] for ARG, carg in zip(T.TO.ARGS, cargs): if ARG is lltype.Void: llargs.append(carg) else: llargs.append(ctypes2lltype(ARG, carg)) if hasattr(container, 'graph'): if LLInterpreter.current_interpreter is None: raise AssertionError llinterp = LLInterpreter.current_interpreter try: llres = llinterp.eval_graph(container.graph, llargs) except LLException, lle: llinterp._store_exception(lle) return 0 else: llres = container._callable(*llargs) assert lltype.typeOf(llres) == T.TO.RESULT if T.TO.RESULT is lltype.Void: return None res = lltype2ctypes(llres) if isinstance(T.TO.RESULT, lltype.Ptr): _all_callbacks_results.append(res) res = ctypes.cast(res, ctypes.c_void_p).value if res is None: return 0 return res if getattr(conftest.option, 'usepdb', False): callback_original = callback def callback(*cargs): try: return callback_original(*cargs) except: import pdb, sys; pdb.post_mortem(sys.exc_traceback) raise if isinstance(T.TO.RESULT, lltype.Ptr): TMod = lltype.Ptr(lltype.FuncType(T.TO.ARGS, lltype.Signed)) ctypes_func_type = get_ctypes_type(TMod) res = ctypes_func_type(callback) ctypes_func_type = get_ctypes_type(T) res = ctypes.cast(res, ctypes_func_type) else: ctypes_func_type = get_ctypes_type(T) res = ctypes_func_type(callback) _callback2obj[ctypes.cast(res, ctypes.c_void_p).value] = container _all_callbacks[key] = res return res
def ctypes2lltype(T, cobj): """Convert the ctypes object 'cobj' to its lltype equivalent. 'T' is the expected lltype type. """ if T is lltype.Void: return None if isinstance(T, lltype.Ptr): if not cobj: # NULL pointer return lltype.nullptr(T.TO) if T is base_ptr_lltype(): return _opaque_list[ctypes.cast(cobj, ctypes.c_void_p).value] if isinstance(T.TO, lltype.Struct): if T.TO._arrayfld is not None: carray = getattr(cobj.contents, T.TO._arrayfld) container = lltype._struct(T.TO, carray.length) else: # special treatment of 'OBJECT' subclasses if get_rtyper() and lltype._castdepth(T.TO, OBJECT) > 0: ctypes_object = get_ctypes_type(lltype.Ptr(OBJECT)) as_obj = ctypes2lltype(lltype.Ptr(OBJECT), ctypes.cast(cobj, ctypes_object)) TObj = get_rtyper().get_type_for_typeptr(as_obj.typeptr) if TObj != T.TO: ctypes_instance = get_ctypes_type(lltype.Ptr(TObj)) return lltype.cast_pointer( T, ctypes2lltype(lltype.Ptr(TObj), ctypes.cast(cobj, ctypes_instance))) container = lltype._struct(T.TO) struct_use_ctypes_storage(container, cobj.contents) addr = ctypes.addressof(cobj.contents) if addr in _parent_cache: setparentstructure(container, _parent_cache[addr]) elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): container = _array_of_unknown_length(T.TO) container._storage = cobj.contents else: container = _array_of_known_length(T.TO) container._storage = cobj.contents elif isinstance(T.TO, lltype.FuncType): cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value if cobjkey in _callback2obj: container = _callback2obj[cobjkey] else: _callable = get_ctypes_trampoline(T.TO, cobj) return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), _callable=_callable) elif isinstance(T.TO, lltype.OpaqueType): if T == llmemory.GCREF: container = _llgcopaque(cobj) else: container = lltype._opaque(T.TO) else: raise NotImplementedError(T) llobj = lltype._ptr(T, container, solid=True) elif T is llmemory.Address: if cobj is None: llobj = llmemory.NULL else: llobj = _lladdress(cobj) elif T is lltype.Char: llobj = chr(cobj) elif T is lltype.UniChar: llobj = unichr(cobj) elif T is lltype.Signed: llobj = cobj elif T is lltype.Bool: assert cobj == True or cobj == False # 0 and 1 work too llobj = bool(cobj) elif T is lltype.SingleFloat: if isinstance(cobj, ctypes.c_float): cobj = cobj.value llobj = r_singlefloat(cobj) elif T is lltype.Void: llobj = cobj else: from pypy.rpython.lltypesystem import rffi try: inttype = rffi.platform.numbertype_to_rclass[T] except KeyError: llobj = cobj else: llobj = inttype(cobj) assert lltype.typeOf(llobj) == T return llobj
def lltype2ctypes(llobj, normalize=True): """Convert the lltype object 'llobj' to its ctypes equivalent. 'normalize' should only be False in tests, where we want to inspect the resulting ctypes object manually. """ if isinstance(llobj, lltype._uninitialized): return uninitialized2ctypes(llobj.TYPE) T = lltype.typeOf(llobj) if isinstance(T, lltype.Ptr): if not llobj: # NULL pointer if T == llmemory.GCREF: return ctypes.c_void_p(0) return get_ctypes_type(T)() if T is base_ptr_lltype(): return new_opaque_object(llobj) if T == llmemory.GCREF: if isinstance(llobj._obj, _llgcopaque): return ctypes.c_void_p(llobj._obj.intval) container = llobj._obj.container T = lltype.Ptr(lltype.typeOf(container)) # otherwise it came from integer and we want a c_void_p with # the same valu else: container = llobj._obj if isinstance(T.TO, lltype.FuncType): # XXX a temporary workaround for comparison of lltype.FuncType key = llobj._obj.__dict__.copy() key['_TYPE'] = repr(key['_TYPE']) items = key.items() items.sort() key = tuple(items) if key in _all_callbacks: return _all_callbacks[key] v1voidlist = [(i, getattr(container, '_void' + str(i), None)) for i in range(len(T.TO.ARGS)) if T.TO.ARGS[i] is lltype.Void] def callback_internal(*cargs): cargs = list(cargs) for v1 in v1voidlist: cargs.insert(v1[0], v1[1]) assert len(cargs) == len(T.TO.ARGS) llargs = [] for ARG, carg in zip(T.TO.ARGS, cargs): if ARG is lltype.Void: llargs.append(carg) else: llargs.append(ctypes2lltype(ARG, carg)) if hasattr(container, 'graph'): if LLInterpreter.current_interpreter is None: raise AssertionError llinterp = LLInterpreter.current_interpreter try: llres = llinterp.eval_graph(container.graph, llargs) except LLException, lle: llinterp._store_exception(lle) return 0 #except: # import pdb # pdb.set_trace() else: try: llres = container._callable(*llargs) except LLException, lle: llinterp = LLInterpreter.current_interpreter llinterp._store_exception(lle) return 0 assert lltype.typeOf(llres) == T.TO.RESULT if T.TO.RESULT is lltype.Void: return None res = lltype2ctypes(llres) if isinstance(T.TO.RESULT, lltype.Ptr): _all_callbacks_results.append(res) res = ctypes.cast(res, ctypes.c_void_p).value if res is None: return 0 return res