Author: Armin Rigo <ar...@tunes.org>
Branch: cffi-1.0
Changeset: r77210:bb885a67145f
Date: 2015-05-08 15:42 +0200
http://bitbucket.org/pypy/pypy/changeset/bb885a67145f/

Log:    more progress

diff --git a/pypy/module/_cffi_backend/ffi_obj.py 
b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -19,6 +19,11 @@
 CONSIDER_FN_AS_FNPTR  = 8
 
 
+def get_ffi_error(space):
+    w_ffitype = space.gettypefor(W_FFIObject)
+    return w_ffitype.getdictvalue(space, 'error')
+
+
 class W_FFIObject(W_Root):
 
     def __init__(self, space, src_ctx=parse_c_type.NULL_CTX):
@@ -29,8 +34,7 @@
             self.cached_types = [None] * parse_c_type.get_num_types(src_ctx)
         else:
             self.cached_types = None
-        w_ffitype = space.gettypefor(W_FFIObject)
-        self.w_FFIError = w_ffitype.getdictvalue(space, 'error')
+        self.w_FFIError = get_ffi_error(space)
 
     @rgc.must_be_light_finalizer
     def __del__(self):
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
@@ -264,6 +264,20 @@
 def new_union_type(space, name):
     return ctypestruct.W_CTypeUnion(space, name)
 
+def detect_custom_layout(w_ctype, sflags, cdef_value, compiler_value,
+                         msg1, msg2="", msg3=""):
+    if compiler_value != cdef_value:
+        if sflags & SF_STD_FIELD_POS:
+            from pypy.module._cffi_backend.ffi_obj import get_ffi_error
+            w_FFIError = get_ffi_error(w_ctype.space)
+            raise oefmt(w_FFIError,
+                    '%s: %s%s%s (cdef says %d, but C compiler says %d).'
+                    ' fix it or use "...;" in the cdef for %s to '
+                    'make it flexible',
+                    w_ctype.name, msg1, msg2, msg3,
+                    cdef_value, compiler_value, w_ctype.name)
+        w_ctype._custom_field_pos = True
+
 @unwrap_spec(w_ctype=ctypeobj.W_CType, totalsize=int, totalalignment=int,
              sflags=int)
 def complete_struct_or_union(space, w_ctype, w_fields, w_ignored=None,
@@ -284,7 +298,7 @@
     fields_w = space.listview(w_fields)
     fields_list = []
     fields_dict = {}
-    custom_field_pos = False
+    w_ctype._custom_field_pos = False
     with_var_array = False
 
     for i in range(len(fields_w)):
@@ -343,7 +357,9 @@
             if foffset >= 0:
                 # a forced field position: ignore the offset just computed,
                 # except to know if we must set 'custom_field_pos'
-                custom_field_pos |= (boffset != foffset * 8)
+                detect_custom_layout(w_ctype, sflags, boffset // 8, foffset,
+                                     "wrong offset for field '",
+                                     fname, "'")
                 boffset = foffset * 8
 
             if (fname == '' and
@@ -361,7 +377,7 @@
                     except KeyError:
                         pass
                 # always forbid such structures from being passed by value
-                custom_field_pos = True
+                w_ctype._custom_field_pos = True
             else:
                 # a regular field
                 fld = ctypestruct.W_CField(ftype, boffset // 8, bs_flag, -1)
@@ -481,22 +497,30 @@
     # Like C, if the size of this structure would be zero, we compute it
     # as 1 instead.  But for ctypes support, we allow the manually-
     # specified totalsize to be zero in this case.
-    got = (boffsetmax + 7) // 8
+    boffsetmax = (boffsetmax + 7) // 8      # bits -> bytes
+    alignedsize = (boffsetmax + alignment - 1) & ~(alignment - 1)
+    alignedsize = alignedsize or 1
+
     if totalsize < 0:
-        totalsize = (got + alignment - 1) & ~(alignment - 1)
-        totalsize = totalsize or 1
-    elif totalsize < got:
-        raise oefmt(space.w_TypeError,
-                    "%s cannot be of size %d: there are fields at least up to "
-                    "%d", w_ctype.name, totalsize, got)
+        totalsize = alignedsize
+    else:
+        detect_custom_layout(w_ctype, sflags, alignedsize, totalsize,
+                             "wrong total size")
+        if totalsize < boffsetmax:
+            raise oefmt(space.w_TypeError,
+                "%s cannot be of size %d: there are fields at least up to %d",
+                w_ctype.name, totalsize, boffsetmax)
     if totalalignment < 0:
         totalalignment = alignment
+    else:
+        detect_custom_layout(w_ctype, sflags, alignment, totalalignment,
+                             "wrong total alignment")
 
     w_ctype.size = totalsize
     w_ctype.alignment = totalalignment
     w_ctype._fields_list = fields_list[:]
     w_ctype._fields_dict = fields_dict
-    w_ctype._custom_field_pos = custom_field_pos
+    #w_ctype._custom_field_pos = ...set above already
     w_ctype._with_var_array = with_var_array
 
 # ____________________________________________________________
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
@@ -291,14 +291,19 @@
         else:
             raise oefmt(space.w_NotImplementedError, "field op=%d", case)
 
+        field_name   = rffi.charp2str(fld.c_name)
+        field_size   = rffi.getintfield(fld, 'c_field_size')
         field_offset = rffi.getintfield(fld, 'c_field_offset')
         if field_offset == -1:
             xxxx
         else:
-            pass #detect_custom_layout()
+            newtype.detect_custom_layout(w_ctype, newtype.SF_STD_FIELD_POS,
+                                         w_ctf.size, field_size,
+                                         "wrong size for field '",
+                                         field_name, "'")
 
         fields_w[i] = space.newtuple([
-            space.wrap(rffi.charp2str(fld.c_name)),
+            space.wrap(field_name),
             w_ctf,
             space.wrap(fbitsize),
             space.wrap(field_offset)])
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to