def PyMemoryView_FromBuffer(space, view): """Create a memoryview object wrapping the given buffer-info structure view. The memoryview object then owns the buffer, which means you shouldn't try to release it yourself: it will be released on deallocation of the memoryview object.""" # XXX this should allocate a PyMemoryViewObject and # copy view into obj.c_view, without creating a new view.c_obj typedescr = get_typedescr(W_MemoryView.typedef) py_obj = typedescr.allocate(space, space.w_memoryview) py_mem = rffi.cast(PyMemoryViewObject, py_obj) mview = py_mem.c_view mview.c_buf = view.c_buf mview.c_obj = view.c_obj mview.c_len = view.c_len mview.c_itemsize = view.c_itemsize mview.c_readonly = view.c_readonly mview.c_ndim = view.c_ndim mview.c_format = view.c_format if view.c_strides == rffi.cast(Py_ssize_tP, view.c__strides): py_mem.c_view.c_strides = rffi.cast(Py_ssize_tP, py_mem.c_view.c__strides) for i in range(view.c_ndim): py_mem.c_view.c_strides[i] = view.c_strides[i] else: # some externally allocated memory chunk py_mem.c_view.c_strides = view.c_strides if view.c_shape == rffi.cast(Py_ssize_tP, view.c__shape): py_mem.c_view.c_shape = rffi.cast(Py_ssize_tP, py_mem.c_view.c__shape) for i in range(view.c_ndim): py_mem.c_view.c_shape[i] = view.c_shape[i] else: # some externally allocated memory chunk py_mem.c_view.c_shape = view.c_shape # XXX ignore suboffsets? return py_obj
def PyFrame_New(space, tstate, w_code, w_globals, w_locals): typedescr = get_typedescr(PyFrame.typedef) py_obj = typedescr.allocate(space, space.gettypeobject(PyFrame.typedef)) py_frame = rffi.cast(PyFrameObject, py_obj) space.interp_w(PyCode, w_code) # sanity check py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, w_code)) py_frame.c_f_globals = make_ref(space, w_globals) return py_frame
def type_attach(space, py_obj, w_type): """ Fills a newly allocated PyTypeObject from an existing type. """ from pypy.module.cpyext.object import PyObject_Del assert isinstance(w_type, W_TypeObject) pto = rffi.cast(PyTypeObjectPtr, py_obj) typedescr = get_typedescr(w_type.layout.typedef) # dealloc pto.c_tp_dealloc = typedescr.get_dealloc(space) # buffer protocol if space.is_w(w_type, space.w_str): setup_string_buffer_procs(space, pto) if space.is_w(w_type, space.w_buffer): setup_buffer_buffer_procs(space, pto) pto.c_tp_free = llhelper(PyObject_Del.api_func.functype, PyObject_Del.api_func.get_wrapper(space)) pto.c_tp_alloc = llhelper(PyType_GenericAlloc.api_func.functype, PyType_GenericAlloc.api_func.get_wrapper(space)) if pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: w_typename = space.getattr(w_type, space.wrap('__name__')) heaptype = rffi.cast(PyHeapTypeObject, pto) heaptype.c_ht_name = make_ref(space, w_typename) from pypy.module.cpyext.bytesobject import PyString_AsString pto.c_tp_name = PyString_AsString(space, heaptype.c_ht_name) else: pto.c_tp_name = rffi.str2charp(w_type.name) # uninitialized fields: # c_tp_print, c_tp_getattr, c_tp_setattr # XXX implement # c_tp_compare and the following fields (see http://docs.python.org/c-api/typeobj.html ) w_base = best_base(space, w_type.bases_w) pto.c_tp_base = rffi.cast(PyTypeObjectPtr, make_ref(space, w_base)) builder = space.fromcache(StaticObjectBuilder) if builder.cpyext_type_init is not None: builder.cpyext_type_init.append((pto, w_type)) else: finish_type_1(space, pto) finish_type_2(space, pto, w_type) pto.c_tp_basicsize = rffi.sizeof(typedescr.basestruct) if pto.c_tp_base: if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize: pto.c_tp_basicsize = pto.c_tp_base.c_tp_basicsize # will be filled later on with the correct value # may not be 0 if space.is_w(w_type, space.w_object): pto.c_tp_new = rffi.cast(newfunc, 1) update_all_slots(space, w_type, pto) pto.c_tp_flags |= Py_TPFLAGS_READY return pto
def new_empty_str(space, length): """ Allocate a PyBytesObject and its ob_sval, but without a corresponding interpreter object. The ob_sval may be mutated, until bytes_realize() is called. Refcount of the result is 1. """ typedescr = get_typedescr(space.w_str.layout.typedef) py_obj = typedescr.allocate(space, space.w_str, length) py_str = rffi.cast(PyBytesObject, py_obj) py_str.c_ob_shash = -1 py_str.c_ob_sstate = rffi.cast(rffi.INT, 0) # SSTATE_NOT_INTERNED return py_str
def new_empty_str(space, length): """ Allocate a PyBytesObject and its ob_sval, but without a corresponding interpreter object. The ob_sval may be mutated, until bytes_realize() is called. Refcount of the result is 1. """ typedescr = get_typedescr(space.w_bytes.layout.typedef) py_obj = typedescr.allocate(space, space.w_bytes, length) py_str = rffi.cast(PyBytesObject, py_obj) py_str.c_ob_shash = -1 py_str.c_ob_sstate = rffi.cast(rffi.INT, 0) # SSTATE_NOT_INTERNED return py_str
def _PyObject_NewVar(space, type, itemcount): w_type = from_ref(space, rffi.cast(PyObject, type)) assert isinstance(w_type, W_TypeObject) typedescr = get_typedescr(w_type.instancetypedef) py_obj = typedescr.allocate(space, w_type, itemcount=itemcount) py_obj.c_ob_refcnt = 0 if type.c_tp_itemsize == 0: w_obj = PyObject_Init(space, py_obj, type) else: py_objvar = rffi.cast(PyVarObject, py_obj) w_obj = PyObject_InitVar(space, py_objvar, type, itemcount) return py_obj
def new_empty_tuple(space, length): """ Allocate a PyTupleObject and its array of PyObject *, but without a corresponding interpreter object. The array may be mutated, until tuple_realize() is called. Refcount of the result is 1. """ typedescr = get_typedescr(space.w_tuple.layout.typedef) py_obj = typedescr.allocate(space, space.w_tuple, length) py_tup = rffi.cast(PyTupleObject, py_obj) p = py_tup.c_ob_item for i in range(py_tup.c_ob_size): p[i] = lltype.nullptr(PyObject.TO) return py_obj
def new_empty_unicode(space, length): """ Allocatse a PyUnicodeObject and its buffer, but without a corresponding interpreter object. The buffer may be mutated, until unicode_realize() is called. """ typedescr = get_typedescr(space.w_unicode.instancetypedef) py_obj = typedescr.allocate(space, space.w_unicode) py_uni = rffi.cast(PyUnicodeObject, py_obj) buflen = length + 1 py_uni.c_size = length py_uni.c_buffer = lltype.malloc(rffi.CWCHARP.TO, buflen, flavor="raw", zero=True) return py_uni
def new_empty_tuple(space, length): """ Allocate a PyTupleObject and its array of PyObject *, but without a corresponding interpreter object. The array may be mutated, until tuple_realize() is called. Refcount of the result is 1. """ typedescr = get_typedescr(space.w_tuple.layout.typedef) py_obj = typedescr.allocate(space, space.w_tuple) py_tup = rffi.cast(PyTupleObject, py_obj) py_tup.c_ob_item = lltype.malloc(ObjectItems, length, flavor='raw', zero=True) py_tup.c_ob_size = length return py_tup
def new_empty_str(space, length): """ Allocatse a PyStringObject and its buffer, but without a corresponding interpreter object. The buffer may be mutated, until string_realize() is called. """ typedescr = get_typedescr(space.w_str.instancetypedef) py_obj = typedescr.allocate(space, space.w_str) py_str = rffi.cast(PyStringObject, py_obj) buflen = length + 1 py_str.c_size = length py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw', zero=True) return py_str
def new_empty_str(space, length): """ Allocates a PyBytesObject and its buffer, but without a corresponding interpreter object. The buffer may be mutated, until bytes_realize() is called. """ typedescr = get_typedescr(space.w_bytes.instancetypedef) py_obj = typedescr.allocate(space, space.w_bytes) py_str = rffi.cast(PyBytesObject, py_obj) buflen = length + 1 py_str.c_size = length py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw', zero=True) return py_str
def new_empty_str(space, length): """ Allocate a PyStringObject and its buffer, but without a corresponding interpreter object. The buffer may be mutated, until string_realize() is called. Refcount of the result is 1. """ typedescr = get_typedescr(space.w_str.layout.typedef) py_obj = typedescr.allocate(space, space.w_str) py_str = rffi.cast(PyStringObject, py_obj) buflen = length + 1 py_str.c_size = length py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw', zero=True) return py_str
def new_empty_tuple(space, length): """ Allocate a PyTupleObject and its array of PyObject *, but without a corresponding interpreter object. The array may be mutated, until tuple_realize() is called. Refcount of the result is 1. """ typedescr = get_typedescr(space.w_tuple.layout.typedef) py_obj = typedescr.allocate(space, space.w_tuple) py_tup = rffi.cast(PyTupleObject, py_obj) py_tup.c_ob_item = lltype.malloc(ObjectItems, length, flavor='raw', zero=True, add_memory_pressure=True) py_tup.c_ob_size = length return py_tup
def type_attach(space, py_obj, w_type): """ Fills a newly allocated PyTypeObject from an existing type. """ from pypy.module.cpyext.object import PyObject_Del assert isinstance(w_type, W_TypeObject) pto = rffi.cast(PyTypeObjectPtr, py_obj) typedescr = get_typedescr(w_type.instancetypedef) # dealloc pto.c_tp_dealloc = typedescr.get_dealloc(space) # buffer protocol if space.is_w(w_type, space.w_str): setup_string_buffer_procs(space, pto) pto.c_tp_flags |= Py_TPFLAGS_HEAPTYPE pto.c_tp_free = llhelper(PyObject_Del.api_func.functype, PyObject_Del.api_func.get_wrapper(space)) pto.c_tp_alloc = llhelper(PyType_GenericAlloc.api_func.functype, PyType_GenericAlloc.api_func.get_wrapper(space)) pto.c_tp_name = rffi.str2charp(w_type.getname(space)) pto.c_tp_basicsize = -1 # hopefully this makes malloc bail out pto.c_tp_itemsize = 0 # uninitialized fields: # c_tp_print, c_tp_getattr, c_tp_setattr # XXX implement # c_tp_compare and the following fields (see http://docs.python.org/c-api/typeobj.html ) w_base = best_base(space, w_type.bases_w) pto.c_tp_base = rffi.cast(PyTypeObjectPtr, make_ref(space, w_base)) finish_type_1(space, pto) finish_type_2(space, pto, w_type) pto.c_tp_basicsize = rffi.sizeof(typedescr.basestruct) if pto.c_tp_base: if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize: pto.c_tp_basicsize = pto.c_tp_base.c_tp_basicsize # will be filled later on with the correct value # may not be 0 if space.is_w(w_type, space.w_object): pto.c_tp_new = rffi.cast(newfunc, 1) update_all_slots(space, w_type, pto) pto.c_tp_flags |= Py_TPFLAGS_READY return pto
def new_empty_unicode(space, length): """ Allocate a PyUnicodeObject and its buffer, but without a corresponding interpreter object. The buffer may be mutated, until unicode_realize() is called. Refcount of the result is 1. """ typedescr = get_typedescr(space.w_unicode.layout.typedef) py_obj = typedescr.allocate(space, space.w_unicode) py_uni = rffi.cast(PyUnicodeObject, py_obj) buflen = length + 1 py_uni.c_length = length py_uni.c_str = lltype.malloc(rffi.CWCHARP.TO, buflen, flavor='raw', zero=True, add_memory_pressure=True) py_uni.c_hash = -1 py_uni.c_defenc = lltype.nullptr(PyObject.TO) return py_uni
def new_empty_unicode(space, length): """ Allocate a PyUnicodeObject and its buffer, but without a corresponding interpreter object. The buffer may be mutated, until unicode_realize() is called. Refcount of the result is 1. """ typedescr = get_typedescr(space.w_unicode.layout.typedef) py_obj = typedescr.allocate(space, space.w_unicode) buflen = length + 1 set_wsize(py_obj, length) set_wbuffer( py_obj, lltype.malloc(rffi.CWCHARP.TO, buflen, flavor='raw', zero=True, add_memory_pressure=True)) return py_obj
def type_attach(space, py_obj, w_type, w_userdata=None): """ Fills a newly allocated PyTypeObject from an existing type. """ assert isinstance(w_type, W_TypeObject) pto = rffi.cast(PyTypeObjectPtr, py_obj) typedescr = get_typedescr(w_type.layout.typedef) if space.is_w(w_type, space.w_bytes): pto.c_tp_itemsize = 1 elif space.is_w(w_type, space.w_tuple): pto.c_tp_itemsize = rffi.sizeof(PyObject) # buffer protocol setup_buffer_procs(space, w_type, pto) state = space.fromcache(State) pto.c_tp_free = state.C.PyObject_Free pto.c_tp_alloc = state.C.PyType_GenericAlloc builder = state.builder if ((pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE) != 0 and builder.cpyext_type_init is None): # this ^^^ is not None only during startup of cpyext. At that # point we might get into troubles by doing make_ref() when # things are not initialized yet. So in this case, simply use # str2charp() and "leak" the string. w_typename = space.getattr(w_type, space.newtext('__name__')) heaptype = cts.cast('PyHeapTypeObject*', pto) heaptype.c_ht_name = make_ref(space, w_typename) from pypy.module.cpyext.bytesobject import PyString_AsString pto.c_tp_name = cts.cast('const char *', PyString_AsString(space, heaptype.c_ht_name)) else: pto.c_tp_name = cts.cast('const char*', rffi.str2charp(w_type.name)) # uninitialized fields: # c_tp_print # XXX implement # c_tp_compare and more? w_base = best_base(space, w_type.bases_w) pto.c_tp_base = rffi.cast(PyTypeObjectPtr, make_ref(space, w_base)) # dealloc if space.gettypeobject(w_type.layout.typedef) is w_type: # only for the exact type, like 'space.w_tuple' or 'space.w_list' pto.c_tp_dealloc = typedescr.get_dealloc(space) else: # for all subtypes, use base's dealloc (requires sorting in attach_all) pto.c_tp_dealloc = pto.c_tp_base.c_tp_dealloc if not pto.c_tp_dealloc: # strange, but happens (ABCMeta) pto.c_tp_dealloc = state.C._PyPy_subtype_dealloc if builder.cpyext_type_init is not None: builder.cpyext_type_init.append((pto, w_type)) else: finish_type_1(space, pto, w_type.bases_w) finish_type_2(space, pto, w_type) pto.c_tp_basicsize = rffi.sizeof(typedescr.basestruct) if pto.c_tp_base: if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize: pto.c_tp_basicsize = pto.c_tp_base.c_tp_basicsize if pto.c_tp_itemsize < pto.c_tp_base.c_tp_itemsize: pto.c_tp_itemsize = pto.c_tp_base.c_tp_itemsize if w_type.is_heaptype(): update_all_slots(space, w_type, pto) else: update_all_slots_builtin(space, w_type, pto) # XXX generlize this pattern for various slot functions implemented in C if space.is_w(w_type, space.w_tuple): pto.c_tp_new = state.C.tuple_new if not pto.c_tp_new: base_object_pyo = make_ref(space, space.w_object) base_object_pto = rffi.cast(PyTypeObjectPtr, base_object_pyo) flags = rffi.cast(lltype.Signed, pto.c_tp_flags) if pto.c_tp_base != base_object_pto or flags & Py_TPFLAGS_HEAPTYPE: pto.c_tp_new = pto.c_tp_base.c_tp_new decref(space, base_object_pyo) pto.c_tp_flags |= Py_TPFLAGS_READY return pto
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 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 type_attach(space, py_obj, w_type): """ Fills a newly allocated PyTypeObject from an existing type. """ from pypy.module.cpyext.object import PyObject_Free assert isinstance(w_type, W_TypeObject) pto = rffi.cast(PyTypeObjectPtr, py_obj) typedescr = get_typedescr(w_type.layout.typedef) # dealloc if space.gettypeobject(w_type.layout.typedef) is w_type: # only for the exact type, like 'space.w_tuple' or 'space.w_list' pto.c_tp_dealloc = typedescr.get_dealloc().get_llhelper(space) else: # for all subtypes, use subtype_dealloc() pto.c_tp_dealloc = llslot(space, subtype_dealloc) if space.is_w(w_type, space.w_str): pto.c_tp_itemsize = 1 elif space.is_w(w_type, space.w_tuple): pto.c_tp_itemsize = rffi.sizeof(PyObject) # buffer protocol setup_buffer_procs(space, w_type, pto) pto.c_tp_free = llslot(space, PyObject_Free) pto.c_tp_alloc = llslot(space, PyType_GenericAlloc) builder = space.fromcache(StaticObjectBuilder) if ((pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE) != 0 and builder.cpyext_type_init is None): # this ^^^ is not None only during startup of cpyext. At that # point we might get into troubles by doing make_ref() when # things are not initialized yet. So in this case, simply use # str2charp() and "leak" the string. w_typename = space.getattr(w_type, space.wrap('__name__')) heaptype = rffi.cast(PyHeapTypeObject, pto) heaptype.c_ht_name = make_ref(space, w_typename) from pypy.module.cpyext.bytesobject import PyString_AsString pto.c_tp_name = PyString_AsString(space, heaptype.c_ht_name) else: pto.c_tp_name = rffi.str2charp(w_type.name) # uninitialized fields: # c_tp_print # XXX implement # c_tp_compare and more? w_base = best_base(space, w_type.bases_w) pto.c_tp_base = rffi.cast(PyTypeObjectPtr, make_ref(space, w_base)) if builder.cpyext_type_init is not None: builder.cpyext_type_init.append((pto, w_type)) else: finish_type_1(space, pto) finish_type_2(space, pto, w_type) pto.c_tp_basicsize = rffi.sizeof(typedescr.basestruct) if pto.c_tp_base: if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize: pto.c_tp_basicsize = pto.c_tp_base.c_tp_basicsize if pto.c_tp_itemsize < pto.c_tp_base.c_tp_itemsize: pto.c_tp_itemsize = pto.c_tp_base.c_tp_itemsize # will be filled later on with the correct value # may not be 0 if space.is_w(w_type, space.w_object): pto.c_tp_new = rffi.cast(newfunc, 1) update_all_slots(space, w_type, pto) pto.c_tp_flags |= Py_TPFLAGS_READY return pto