[pypy-commit] pypy cffi-1.0: in-progress

arigo noreply at buildbot.pypy.org
Fri May 8 15:04:01 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r77208:2d29bf282988
Date: 2015-05-08 15:04 +0200
http://bitbucket.org/pypy/pypy/changeset/2d29bf282988/

Log:	in-progress

diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -48,7 +48,9 @@
         # Force a "lazy" struct to become "forced"; complain if we are "opaque".
         if self._fields_list is None:
             self.check_complete()
-            XXXXX
+            #
+            from pypy.module._cffi_backend import realize_c_type
+            realize_c_type.do_realize_lazy_struct(self)
 
     def _alignof(self):
         self.check_complete(w_errorcls=self.space.w_ValueError)
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -226,6 +226,7 @@
 SF_GCC_LITTLE_ENDIAN  = 0x40
 
 SF_PACKED             = 0x08
+SF_STD_FIELD_POS      = 0x80
 
 
 if sys.platform == 'win32':
diff --git a/pypy/module/_cffi_backend/parse_c_type.py b/pypy/module/_cffi_backend/parse_c_type.py
--- a/pypy/module/_cffi_backend/parse_c_type.py
+++ b/pypy/module/_cffi_backend/parse_c_type.py
@@ -33,11 +33,10 @@
                        ('first_field_index', rffi.INT),
                        ('num_fields', rffi.INT))
 FIELD_S = rffi.CStruct('struct _cffi_field_s',
-    ## const char *name;
-    ## size_t field_offset;
-    ## size_t field_size;
-    ## _cffi_opcode_t field_type_op;
-    )
+                       ('name', rffi.CCHARP),
+                       ('field_offset', rffi.SIZE_T),
+                       ('field_size', rffi.SIZE_T),
+                       ('field_type_op', _CFFI_OPCODE_T))
 ENUM_S = rffi.CStruct('struct _cffi_enum_s',
                        ('name', rffi.CCHARP),
                        ('type_index', rffi.INT),
diff --git a/pypy/module/_cffi_backend/realize_c_type.py b/pypy/module/_cffi_backend/realize_c_type.py
--- a/pypy/module/_cffi_backend/realize_c_type.py
+++ b/pypy/module/_cffi_backend/realize_c_type.py
@@ -4,7 +4,8 @@
 from pypy.interpreter.error import oefmt
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.module._cffi_backend.ctypeobj import W_CType
-from pypy.module._cffi_backend import cffi_opcode, newtype
+from pypy.module._cffi_backend import cffi_opcode, newtype, ctypestruct
+from pypy.module._cffi_backend import parse_c_type
 
 
 def getop(op):
@@ -164,18 +165,23 @@
         return ffi.cached_types[type_index] #found already in the "primary" slot
 
     w_ctype = None
-    s_flags = rffi.getintfield(s, 'c_flags')
-    if (s_flags & cffi_opcode.F_EXTERNAL) == 0:
+    c_flags = rffi.getintfield(s, 'c_flags')
+    if (c_flags & cffi_opcode.F_EXTERNAL) == 0:
         space = ffi.space
-        if (s_flags & cffi_opcode.F_UNION) != 0:
+        if (c_flags & cffi_opcode.F_UNION) != 0:
             name = _realize_name("union ", s.c_name)
-            x = newtype.new_union_type(space, name)
+            x = ctypestruct.W_CTypeUnion(space, name)
         else:
             name = _realize_name("struct ", s.c_name)
-            x = newtype.new_struct_type(space, name)
+            x = ctypestruct.W_CTypeStruct(space, name)
         if rffi.getintfield(s, 'c_first_field_index') >= 0:
             w_ctype = x
-            xxxx
+            w_ctype.size = rffi.getintfield(s, 'c_size')
+            w_ctype.alignment = rffi.getintfield(s, 'c_alignment')
+            # w_ctype._field_list and other underscore fields are still
+            # None, making it a "lazy" (i.e. "non-forced") kind of struct
+            w_ctype._lazy_ffi = ffi
+            w_ctype._lazy_s = s
     else:
         yyyy
 
@@ -187,7 +193,7 @@
         # a C expression to get its size.  We have to rely on
         # complete_struct_or_union() to compute it now.
         try:
-            xxxx / do_realize_lazy_struct(w_ctype)
+            do_realize_lazy_struct(ffi, w_ctype)
         except:
             ffi.cached_types[type_index] = None
             raise
@@ -257,3 +263,69 @@
         ffi.cached_types[index] = x
 
     return x
+
+
+def do_realize_lazy_struct(w_ctype):
+    """This is called by W_CTypeStructOrUnion.force_lazy_struct().
+    """
+    assert isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion)
+    space = w_ctype.space
+    ffi = w_ctype._lazy_ffi
+    s = w_ctype._lazy_s
+    assert w_ctype.size != -1      # not an opaque
+    assert ffi is not None         # still lazy
+
+    first_field = rffi.getintfield(s, 'c_first_field_index')
+    num_fields = rffi.getintfield(s, 'c_num_fields')
+    fields_w = [None] * num_fields
+
+    for i in range(num_fields):
+        fbitsize = -1
+        fld = ffi.ctxobj.ctx.c_fields[first_field + i]
+        op = rffi.getintfield(fld, 'c_field_type_op')
+        case = getop(op)
+
+        if case == cffi_opcode.OP_NOOP:
+            # standard field
+            w_ctf = realize_c_type(ffi, ffi.ctxobj.ctx.c_types, getarg(op))
+        else:
+            raise oefmt(space.w_NotImplementedError, "field op=%d", case)
+
+        field_offset = rffi.getintfield(fld, 'c_field_offset')
+        if field_offset == -1:
+            xxxx
+        else:
+            pass #detect_custom_layout()
+
+        fields_w[i] = space.newtuple([
+            space.wrap(rffi.charp2str(fld.c_name)),
+            w_ctf,
+            space.wrap(fbitsize),
+            space.wrap(field_offset)])
+
+    sflags = 0
+    c_flags = rffi.getintfield(s, 'c_flags')
+    if c_flags & cffi_opcode.F_CHECK_FIELDS:
+        sflags |= newtype.SF_STD_FIELD_POS
+    if c_flags & cffi_opcode.F_PACKED:
+        sflags |= newtype.SF_PACKED
+
+    assert w_ctype.size      == rffi.getintfield(s, 'c_size')
+    assert w_ctype.alignment == rffi.getintfield(s, 'c_alignment')
+    try:
+        w_ctype.size = -1              # make opaque again
+        newtype.complete_struct_or_union(
+            space, w_ctype, space.newlist(fields_w), space.w_None,
+            totalsize = rffi.getintfield(s, 'c_size'),
+            totalalignment = rffi.getintfield(s, 'c_alignment'),
+            sflags = sflags)
+    except:
+        w_ctype.size      = rffi.getintfield(s, 'c_size')       # restore
+        w_ctype.alignment = rffi.getintfield(s, 'c_alignment')  # restore
+        raise
+    assert w_ctype.size      == rffi.getintfield(s, 'c_size')
+    assert w_ctype.alignment == rffi.getintfield(s, 'c_alignment')
+    assert w_ctype._fields_list is not None       # not lazy any more
+
+    w_ctype._lazy_ffi = None
+    w_ctype._lazy_s = lltype.nullptr(parse_c_type.FIELD_S)


More information about the pypy-commit mailing list