Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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
Example #9
0
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
Example #10
0
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
Example #11
0
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
Example #12
0
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
Example #13
0
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
Example #14
0
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
Example #15
0
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
Example #16
0
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
Example #17
0
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
Example #18
0
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
Example #19
0
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
Example #20
0
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
Example #21
0
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
Example #22
0
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
Example #23
0
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='')
Example #24
0
File: api.py Project: juokaz/pypy
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='')
Example #25
0
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