def _type_realize(space, py_obj): """ Creates an interpreter type from a PyTypeObject structure. """ # missing: # inheriting tp_as_* slots # unsupported: # tp_mro, tp_subclasses py_type = rffi.cast(PyTypeObjectPtr, py_obj) if not py_type.c_tp_base: # borrowed reference, but w_object is unlikely to disappear base = make_ref(space, space.w_object) Py_DecRef(space, base) py_type.c_tp_base = rffi.cast(PyTypeObjectPtr, base) finish_type_1(space, py_type) w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type)) w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype) track_reference(space, py_obj, w_obj) w_obj.__init__(space, py_type) w_obj.ready() finish_type_2(space, py_type, w_obj) state = space.fromcache(RefcountState) state.non_heaptypes_w.append(w_obj) return w_obj
def int_realize(space, obj): intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, obj).c_ob_ival) w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) w_obj = space.allocate_instance(W_IntObject, w_type) w_obj.__init__(intval) track_reference(space, obj, w_obj) return w_obj
def methoddescr_realize(space, obj): # XXX NOT TESTED When is this ever called? method = rffi.cast(lltype.Ptr(PyMethodDef), obj) w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) w_obj = space.allocate_instance(W_PyCMethodObject, w_type) w_obj.__init__(space, method, w_type) track_reference(space, obj, w_obj) return w_obj
def int_realize(space, obj): intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, obj).c_ob_ival) w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) w_obj = space.allocate_instance(W_IntObject, w_type) w_obj.__init__(intval) track_reference(space, obj, w_obj) state = space.fromcache(RefcountState) state.set_lifeline(w_obj, obj) return w_obj
def unicode_realize(space, py_obj): """ Creates the unicode in the interpreter. The PyUnicodeObject buffer must not be modified after this call. """ py_uni = rffi.cast(PyUnicodeObject, py_obj) s = rffi.wcharpsize2unicode(py_uni.c_buffer, py_uni.c_size) w_obj = space.wrap(s) track_reference(space, py_obj, w_obj) return w_obj
def string_realize(space, py_obj): """ Creates the string in the interpreter. The PyStringObject buffer must not be modified after this call. """ py_str = rffi.cast(PyStringObject, py_obj) s = rffi.charpsize2str(py_str.c_buffer, py_str.c_size) w_obj = space.wrap(s) track_reference(space, py_obj, w_obj) return w_obj
def unicode_realize(space, py_obj): """ Creates the unicode in the interpreter. The PyUnicodeObject buffer must not be modified after this call. """ py_uni = rffi.cast(PyUnicodeObject, py_obj) s = rffi.wcharpsize2unicode(py_uni.c_str, py_uni.c_length) w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type)) w_obj = space.allocate_instance(unicodeobject.W_UnicodeObject, w_type) w_obj.__init__(s) py_uni.c_hash = space.hash_w(w_obj) track_reference(space, py_obj, w_obj) return w_obj
def unicode_realize(space, py_obj): """ Creates the unicode in the interpreter. The PyUnicodeObject buffer must not be modified after this call. """ py_uni = rffi.cast(PyUnicodeObject, py_obj) length = py_uni.c_length s = wcharpsize2utf8(space, py_uni.c_str, length) w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type)) w_obj = space.allocate_instance(unicodeobject.W_UnicodeObject, w_type) w_obj.__init__(s, length) py_uni.c_hash = space.hash_w(space.newutf8(s, length)) track_reference(space, py_obj, w_obj) return w_obj
def bytes_realize(space, py_obj): """ Creates the string in the interpreter. The PyBytesObject ob_sval must not be modified after this call. """ py_str = rffi.cast(PyBytesObject, py_obj) s = rffi.charpsize2str(py_str.c_ob_sval, py_str.c_ob_size) w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type)) w_obj = space.allocate_instance(W_BytesObject, w_type) w_obj.__init__(s) py_str.c_ob_shash = space.hash_w(w_obj) py_str.c_ob_sstate = rffi.cast(rffi.INT, 1) # SSTATE_INTERNED_MORTAL track_reference(space, py_obj, w_obj) return w_obj
def tuple_realize(space, py_obj): """ Creates the tuple in the interpreter. The PyTupleObject must not be modified after this call. """ py_tup = rffi.cast(PyTupleObject, py_obj) l = py_tup.c_ob_size p = py_tup.c_ob_item items_w = [None] * l for i in range(l): items_w[i] = from_ref(space, p[i]) w_obj = space.newtuple(items_w) track_reference(space, py_obj, w_obj) return w_obj
def _type_realize(space, py_obj): """ Creates an interpreter type from a PyTypeObject structure. """ # missing: # unsupported: # tp_mro, tp_subclasses py_type = rffi.cast(PyTypeObjectPtr, py_obj) if not py_type.c_tp_base: # borrowed reference, but w_object is unlikely to disappear base = as_pyobj(space, space.w_object) py_type.c_tp_base = rffi.cast(PyTypeObjectPtr, base) finish_type_1(space, py_type) if py_type.c_ob_type: w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type)) else: # Somehow the tp_base type is created with no ob_type, notably # PyString_Type and PyBaseString_Type # While this is a hack, cpython does it as well. w_metatype = space.w_type w_obj = rawrefcount.to_obj(W_PyCTypeObject, py_obj) if w_obj is None: w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype) track_reference(space, py_obj, w_obj) # __init__ wraps all slotdefs functions from py_type via add_operators w_obj.__init__(space, py_type) w_obj.ready() finish_type_2(space, py_type, w_obj) base = py_type.c_tp_base if base: # XXX refactor - parts of this are done in finish_type_2 -> inherit_slots if not py_type.c_tp_as_number: py_type.c_tp_as_number = base.c_tp_as_number py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_CHECKTYPES py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_sequence: py_type.c_tp_as_sequence = base.c_tp_as_sequence py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping #if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer return w_obj
def frame_realize(space, py_obj): """ Creates the frame in the interpreter. The PyFrameObject structure must not be modified after this call. """ py_frame = rffi.cast(PyFrameObject, py_obj) py_code = rffi.cast(PyObject, py_frame.c_f_code) w_code = from_ref(space, py_code) code = space.interp_w(PyCode, w_code) w_globals = from_ref(space, py_frame.c_f_globals) frame = space.FrameClass(space, code, w_globals, outer_func=None) frame.f_lineno = rffi.getintfield(py_frame, 'c_f_lineno') w_obj = space.wrap(frame) track_reference(space, py_obj, w_obj) return w_obj
def bytes_realize(space, py_obj): """ Creates the string in the interpreter. The PyBytesObject ob_sval must not be modified after this call. """ py_str = rffi.cast(PyBytesObject, py_obj) s = rffi.charpsize2str(py_str.c_ob_sval, py_str.c_ob_size) w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type)) w_obj = space.allocate_instance(W_BytesObject, w_type) w_obj.__init__(s) # if py_obj has a tp_hash, this will try to call it but the object is # not realized yet py_str.c_ob_shash = space.hash_w(space.newbytes(s)) py_str.c_ob_sstate = rffi.cast(rffi.INT, 1) # SSTATE_INTERNED_MORTAL track_reference(space, py_obj, w_obj) return w_obj
def frame_realize(space, py_obj): """ Creates the frame in the interpreter. The PyFrameObject structure must not be modified after this call. """ py_frame = rffi.cast(PyFrameObject, py_obj) py_code = rffi.cast(PyObject, py_frame.c_f_code) w_code = from_ref(space, py_code) code = space.interp_w(PyCode, w_code) w_globals = from_ref(space, py_frame.c_f_globals) frame = space.FrameClass(space, code, w_globals, closure=None) frame.f_lineno = py_frame.c_f_lineno w_obj = space.wrap(frame) track_reference(space, py_obj, w_obj) return w_obj
def frame_realize(space, py_obj): """ Creates the frame in the interpreter. The PyFrameObject structure must not be modified after this call. """ py_frame = rffi.cast(PyFrameObject, py_obj) py_code = rffi.cast(PyObject, py_frame.c_f_code) w_code = from_ref(space, py_code) code = space.interp_w(PyCode, w_code) w_globals = from_ref(space, py_frame.c_f_globals) frame = space.FrameClass(space, code, w_globals, outer_func=None) d = frame.getorcreatedebug() d.f_lineno = rffi.getintfield(py_frame, 'c_f_lineno') w_obj = space.wrap(frame) track_reference(space, py_obj, w_obj) return w_obj
def _type_realize(space, py_obj): """ Creates an interpreter type from a PyTypeObject structure. """ # missing: # unsupported: # tp_mro, tp_subclasses py_type = rffi.cast(PyTypeObjectPtr, py_obj) if not py_type.c_tp_base: # borrowed reference, but w_object is unlikely to disappear base = as_pyobj(space, space.w_object) py_type.c_tp_base = rffi.cast(PyTypeObjectPtr, base) finish_type_1(space, py_type) if py_type.c_ob_type: w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type)) else: # Somehow the tp_base type is created with no ob_type, notably # PyString_Type and PyBaseString_Type # While this is a hack, cpython does it as well. w_metatype = space.w_type w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype) track_reference(space, py_obj, w_obj) # __init__ wraps all slotdefs functions from py_type via add_operators w_obj.__init__(space, py_type) w_obj.ready() finish_type_2(space, py_type, w_obj) base = py_type.c_tp_base if base: # XXX refactor - parts of this are done in finish_type_2 -> inherit_slots if not py_type.c_tp_as_number: py_type.c_tp_as_number = base.c_tp_as_number py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_CHECKTYPES py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_sequence: py_type.c_tp_as_sequence = base.c_tp_as_sequence py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping #if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer return w_obj
def tuple_realize(space, py_obj): """ Creates the tuple in the interpreter. The PyTupleObject must not be modified after this call. We check that it does not contain any NULLs at this point (which would correspond to half-broken W_TupleObjects). """ py_tup = rffi.cast(PyTupleObject, py_obj) l = py_tup.c_ob_size p = py_tup.c_ob_item items_w = [None] * l for i in range(l): w_item = from_ref(space, p[i]) if w_item is None: fatalerror_notb( "Fatal error in cpyext, CPython compatibility layer: " "converting a PyTupleObject into a W_TupleObject, " "but found NULLs as items") items_w[i] = w_item w_obj = space.newtuple(items_w) track_reference(space, py_obj, w_obj) return w_obj
def dict_realize(space, py_obj): """ Creates the dict in the interpreter """ w_obj = space.newdict() track_reference(space, py_obj, w_obj)
def build_bridge(space): "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) from rpython.translator.c.database import LowLevelDatabase db = LowLevelDatabase() generate_macros(export_symbols, prefix='cpyexttest') # 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; RPY_EXTERN 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" "#include <src/thread.c>\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', 'cpyexttest') 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_') or name.startswith('cpyexttestExc_'): # 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, translating=False) return modulename.new(ext='')
def init_typeobject(space): # Probably a hack space.model.typeorder[W_PyCTypeObject] = [(W_PyCTypeObject, None), (W_TypeObject, None), (W_Root, None)] make_typedescr(space.w_type.instancetypedef, basestruct=PyTypeObject, alloc=type_alloc, attach=type_attach, realize=type_realize, dealloc=type_dealloc) # some types are difficult to create because of cycles. # - object.ob_type = type # - type.ob_type = type # - tuple.ob_type = type # - type.tp_base = object # - tuple.tp_base = object # - type.tp_bases is a tuple # - object.tp_bases is a tuple # - tuple.tp_bases is a tuple # insert null placeholders to please create_ref() track_reference(space, lltype.nullptr(PyObject.TO), space.w_type) track_reference(space, lltype.nullptr(PyObject.TO), space.w_object) track_reference(space, lltype.nullptr(PyObject.TO), space.w_tuple) track_reference(space, lltype.nullptr(PyObject.TO), space.w_str) # create the objects py_type = create_ref(space, space.w_type) py_object = create_ref(space, space.w_object) py_tuple = create_ref(space, space.w_tuple) py_str = create_ref(space, space.w_str) # form cycles pto_type = rffi.cast(PyTypeObjectPtr, py_type) py_type.c_ob_type = pto_type py_object.c_ob_type = pto_type py_tuple.c_ob_type = pto_type pto_object = rffi.cast(PyTypeObjectPtr, py_object) pto_type.c_tp_base = pto_object pto_tuple = rffi.cast(PyTypeObjectPtr, py_tuple) pto_tuple.c_tp_base = pto_object pto_type.c_tp_bases.c_ob_type = pto_tuple pto_object.c_tp_bases.c_ob_type = pto_tuple pto_tuple.c_tp_bases.c_ob_type = pto_tuple for typ in (py_type, py_object, py_tuple, py_str): heaptype = rffi.cast(PyHeapTypeObject, typ) heaptype.c_ht_name.c_ob_type = pto_type # Restore the mapping track_reference(space, py_type, space.w_type, replace=True) track_reference(space, py_object, space.w_object, replace=True) track_reference(space, py_tuple, space.w_tuple, replace=True) track_reference(space, py_str, space.w_str, replace=True)
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='')