def get_array_token(T, translate_support_code): # T can be an array or a var-sized structure if translate_support_code: basesize = llmemory.sizeof(T, 0) if isinstance(T, lltype.Struct): SUBARRAY = getattr(T, T._arrayfld) itemsize = llmemory.sizeof(SUBARRAY.OF) ofs_length = (llmemory.offsetof(T, T._arrayfld) + llmemory.ArrayLengthOffset(SUBARRAY)) else: if T._hints.get('nolength', None): ofs_length = -1 else: ofs_length = llmemory.ArrayLengthOffset(T) itemsize = llmemory.sizeof(T.OF) else: if isinstance(T, lltype.Struct): assert T._arrayfld is not None, "%r is not variable-sized" % (T, ) cstruct = ll2ctypes.get_ctypes_type(T) cfield = getattr(cstruct, T._arrayfld) before_array_part = cfield.offset T = getattr(T, T._arrayfld) else: before_array_part = 0 carray = ll2ctypes.get_ctypes_type(T) if T._hints.get('nolength', None): ofs_length = -1 else: assert carray.length.size == WORD ofs_length = before_array_part + carray.length.offset basesize = before_array_part + carray.items.offset carrayitem = ll2ctypes.get_ctypes_type(T.OF) itemsize = ctypes.sizeof(carrayitem) return basesize, itemsize, ofs_length
def get_array_token(T, translate_support_code): # T can be an array or a var-sized structure if translate_support_code: basesize = llmemory.sizeof(T, 0) if isinstance(T, lltype.Struct): SUBARRAY = getattr(T, T._arrayfld) itemsize = llmemory.sizeof(SUBARRAY.OF) ofs_length = (llmemory.offsetof(T, T._arrayfld) + llmemory.ArrayLengthOffset(SUBARRAY)) else: itemsize = llmemory.sizeof(T.OF) ofs_length = llmemory.ArrayLengthOffset(T) else: if isinstance(T, lltype.Struct): assert T._arrayfld is not None, "%r is not variable-sized" % (T,) cstruct = ll2ctypes.get_ctypes_type(T) cfield = getattr(cstruct, T._arrayfld) before_array_part = cfield.offset T = getattr(T, T._arrayfld) else: before_array_part = 0 carray = ll2ctypes.get_ctypes_type(T) assert carray.length.size == WORD ofs_length = before_array_part + carray.length.offset basesize = before_array_part + carray.items.offset carrayitem = ll2ctypes.get_ctypes_type(T.OF) itemsize = ctypes.sizeof(carrayitem) return basesize, itemsize, ofs_length
def test_indirect_recursive_struct_more(self): NODE = lltype.ForwardReference() NODE2 = lltype.Struct('NODE2', ('ping', lltype.Ptr(NODE))) NODE.become(lltype.Struct('NODE', ('pong', NODE2))) # Building NODE2 first used to fail. get_ctypes_type(NODE2) CNODEPTR = get_ctypes_type(NODE) pc = CNODEPTR() pc.pong.ping = ctypes.pointer(pc) p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc)) assert p.pong.ping == p
def get_field_token(STRUCT, fieldname, translate_support_code): if translate_support_code: return (llmemory.offsetof(STRUCT, fieldname), get_size(getattr(STRUCT, fieldname), True)) cstruct = ll2ctypes.get_ctypes_type(STRUCT) cfield = getattr(cstruct, fieldname) return (cfield.offset, cfield.size)
def get_size(TYPE, translate_support_code): if translate_support_code: if TYPE._is_varsize(): return llmemory.sizeof(TYPE, 0) return llmemory.sizeof(TYPE) ctype = ll2ctypes.get_ctypes_type(TYPE) return ctypes.sizeof(ctype)
def test_recursive_struct_more(self): NODE = lltype.ForwardReference() NODE.become(lltype.Struct('NODE', ('value', lltype.Signed), ('next', lltype.Ptr(NODE)))) CNODEPTR = get_ctypes_type(NODE) pc = CNODEPTR() pc.value = 42 pc.next = ctypes.pointer(pc) p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc)) assert p.value == 42 assert p.next == p pc2 = lltype2ctypes(p) assert pc2.contents.value == 42 assert pc2.contents.next.contents.value == 42
def test_recursive_struct_more(self): NODE = lltype.ForwardReference() NODE.become( lltype.Struct('NODE', ('value', lltype.Signed), ('next', lltype.Ptr(NODE)))) CNODEPTR = get_ctypes_type(NODE) pc = CNODEPTR() pc.value = 42 pc.next = ctypes.pointer(pc) p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc)) assert p.value == 42 assert p.next == p pc2 = lltype2ctypes(p) assert pc2.contents.value == 42 assert pc2.contents.next.contents.value == 42
def build_bridge(space): "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) from pypy.translator.c.database import LowLevelDatabase db = LowLevelDatabase() generate_macros(export_symbols, rename=True, do_deref=True) # Structure declaration code members = [] structindex = {} for name, func in sorted(FUNCTIONS.iteritems()): restype, args = c_function_signature(db, func) members.append('%s (*%s)(%s);' % (restype, name, args)) structindex[name] = len(structindex) structmembers = '\n'.join(members) struct_declaration_code = """\ struct PyPyAPI { %(members)s } _pypyAPI; struct PyPyAPI* pypyAPI = &_pypyAPI; """ % dict(members=structmembers) functions = generate_decls_and_callbacks(db, export_symbols) global_objects = [] for name, (typ, expr) in GLOBALS.iteritems(): if "#" in name: continue if typ == 'PyDateTime_CAPI*': continue elif name.startswith('PyExc_'): global_objects.append('%s _%s;' % (typ[:-1], name)) else: global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) prologue = "#include <Python.h>\n" code = (prologue + struct_declaration_code + global_code + '\n' + '\n'.join(functions)) eci = build_eci(True, export_symbols, code) eci = eci.compile_shared_lib( outputfilename=str(udir / "module_cache" / "pypyapi")) modulename = py.path.local(eci.libraries[-1]) run_bootstrap_functions(space) # load the bridge, and init structure import ctypes bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL) space.fromcache(State).install_dll(eci) # populate static data for name, (typ, expr) in GLOBALS.iteritems(): from pypy.module import cpyext w_obj = eval(expr) if name.endswith('#'): name = name[:-1] isptr = False else: isptr = True if name.startswith('PyExc_'): isptr = False INTERPLEVEL_API[name] = w_obj name = name.replace('Py', 'PyPy') if isptr: ptr = ctypes.c_void_p.in_dll(bridge, name) if typ == 'PyObject*': value = make_ref(space, w_obj) elif typ == 'PyDateTime_CAPI*': value = w_obj else: assert False, "Unknown static pointer: %s %s" % (typ, name) ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): if name.startswith('PyPyExc_'): # we already have the pointer in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) else: # we have a structure, get its address in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) from pypy.module.cpyext.pyobject import ( track_reference, get_typedescr) w_type = space.type(w_obj) typedescr = get_typedescr(w_type.instancetypedef) py_obj.c_ob_refcnt = 1 py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr, make_ref(space, w_type)) typedescr.attach(space, py_obj, w_obj) track_reference(space, py_obj, w_obj) else: assert False, "Unknown static object: %s %s" % (typ, name) pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') # implement structure initialization code for name, func in FUNCTIONS.iteritems(): if name.startswith('cpyext_'): # XXX hack continue pypyAPI[structindex[name]] = ctypes.cast( ll2ctypes.lltype2ctypes(func.get_llhelper(space)), ctypes.c_void_p) setup_va_functions(eci) setup_init_functions(eci) return modulename.new(ext='')
def build_bridge(space): "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) from pypy.translator.c.database import LowLevelDatabase db = LowLevelDatabase() generate_macros(export_symbols, rename=True, do_deref=True) # Structure declaration code members = [] structindex = {} for name, func in sorted(FUNCTIONS.iteritems()): restype, args = c_function_signature(db, func) members.append('%s (*%s)(%s);' % (restype, name, args)) structindex[name] = len(structindex) structmembers = '\n'.join(members) struct_declaration_code = """\ struct PyPyAPI { %(members)s } _pypyAPI; struct PyPyAPI* pypyAPI = &_pypyAPI; """ % dict(members=structmembers) functions = generate_decls_and_callbacks(db, export_symbols) global_objects = [] for name, (typ, expr) in GLOBALS.iteritems(): if "#" in name: continue if typ == 'PyDateTime_CAPI*': continue elif name.startswith('PyExc_'): global_objects.append('%s _%s;' % (typ[:-1], name)) else: global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) prologue = "#include <Python.h>\n" code = (prologue + struct_declaration_code + global_code + '\n' + '\n'.join(functions)) eci = build_eci(True, export_symbols, code) eci = eci.compile_shared_lib(outputfilename=str(udir / "module_cache" / "pypyapi")) modulename = py.path.local(eci.libraries[-1]) run_bootstrap_functions(space) # load the bridge, and init structure import ctypes bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL) space.fromcache(State).install_dll(eci) # populate static data for name, (typ, expr) in GLOBALS.iteritems(): from pypy.module import cpyext w_obj = eval(expr) if name.endswith('#'): name = name[:-1] isptr = False else: isptr = True if name.startswith('PyExc_'): isptr = False INTERPLEVEL_API[name] = w_obj name = name.replace('Py', 'PyPy') if isptr: ptr = ctypes.c_void_p.in_dll(bridge, name) if typ == 'PyObject*': value = make_ref(space, w_obj) elif typ == 'PyDateTime_CAPI*': value = w_obj else: assert False, "Unknown static pointer: %s %s" % (typ, name) ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): if name.startswith('PyPyExc_'): # we already have the pointer in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll( bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) else: # we have a structure, get its address in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll( bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) from pypy.module.cpyext.pyobject import (track_reference, get_typedescr) w_type = space.type(w_obj) typedescr = get_typedescr(w_type.instancetypedef) py_obj.c_ob_refcnt = 1 py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr, make_ref(space, w_type)) typedescr.attach(space, py_obj, w_obj) track_reference(space, py_obj, w_obj) else: assert False, "Unknown static object: %s %s" % (typ, name) pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') # implement structure initialization code for name, func in FUNCTIONS.iteritems(): if name.startswith('cpyext_'): # XXX hack continue pypyAPI[structindex[name]] = ctypes.cast( ll2ctypes.lltype2ctypes(func.get_llhelper(space)), ctypes.c_void_p) setup_va_functions(eci) setup_init_functions(eci) return modulename.new(ext='')
def test_typedef(self): assert ctypes2lltype(lltype.Typedef(lltype.Signed, 'test'), 6) == 6 assert ctypes2lltype(lltype.Typedef(lltype.Float, 'test2'), 3.4) == 3.4 assert get_ctypes_type(lltype.Signed) == get_ctypes_type( lltype.Typedef(lltype.Signed, 'test3'))