[pypy-commit] cffi cpy-extension: Good, we can now declare array fields without specifying the length,

arigo noreply at buildbot.pypy.org
Wed Jun 13 22:01:13 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: cpy-extension
Changeset: r314:61cbe88492c3
Date: 2012-06-13 22:01 +0200
http://bitbucket.org/cffi/cffi/changeset/61cbe88492c3/

Log:	Good, we can now declare array fields without specifying the length,
	and let verify() fill that in.

diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -119,6 +119,9 @@
         self.item = item
         self.length = length
 
+    def resolve_length(self, newlength):
+        return ArrayType(self.item, newlength)
+
     def get_c_name(self, replace_with=''):
         if self.length is None:
             brackets = '[]'
@@ -158,20 +161,44 @@
         if self.fixedlayout is None:
             lst = zip(self.fldnames, fldtypes, self.fldbitsize)
             ffi._backend.complete_struct_or_union(BType, lst, self)
+            #
         else:
             fieldofs, fieldsize, totalsize, totalalignment = self.fixedlayout
-            for fname, ftype, fsize in zip(self.fldnames, fldtypes, fieldsize):
-                if ffi.sizeof(ftype) != fsize:
-                    from .ffiplatform import VerificationError
-                    raise VerificationError, (
+            for i in range(len(self.fldnames)):
+                fsize = fieldsize[i]
+                ftype = self.fldtypes[i]
+                #
+                if isinstance(ftype, ArrayType) and ftype.length is None:
+                    # fix the length to match the total size
+                    BItemType = ffi._get_cached_btype(ftype.item)
+                    nlen, nrest = divmod(fsize, ffi.sizeof(BItemType))
+                    if nrest != 0:
+                        self._verification_error(
+                            "field '%s.%s' has a bogus size?" % (
+                            self.name, self.fldnames[i]))
+                    ftype = ftype.resolve_length(nlen)
+                    self.fldtypes = (self.fldtypes[:i] + (ftype,) +
+                                     self.fldtypes[i+1:])
+                    BArrayType = ffi._get_cached_btype(ftype)
+                    fldtypes = (fldtypes[:i] + (BArrayType,) +
+                                fldtypes[i+1:])
+                    continue
+                #
+                bitemsize = ffi.sizeof(fldtypes[i])
+                if bitemsize != fsize:
+                    self._verification_error(
                         "field '%s.%s' is declared as %d bytes, but is "
-                        "really %d bytes" % (self.name, fname,
-                                             ffi.sizeof(ftype), fsize))
+                        "really %d bytes" % (self.name, self.fldnames[i],
+                                             bitemsize, fsize))
             lst = zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs)
             ffi._backend.complete_struct_or_union(BType, lst, self,
                                                   totalsize, totalalignment)
         return BType
 
+    def _verification_error(self, msg):
+        from .ffiplatform import VerificationError
+        raise VerificationError(msg)
+
 
 class StructType(StructOrUnion):
     kind = 'struct'
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -220,9 +220,8 @@
     assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
 
 def test_struct_array_guess_length():
-    py.test.skip("in-progress")
     ffi = FFI()
-    ffi.cdef("struct foo_s { int a[]; ...; };")
+    ffi.cdef("struct foo_s { int a[]; ...; };")    # <= no declared length
     ffi.verify("struct foo_s { int x; int a[17]; int y; };")
     assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
     s = ffi.new("struct foo_s")


More information about the pypy-commit mailing list