[pypy-commit] cffi linux-only: Finish the (non-partial) struct verification. For now uses

arigo noreply at buildbot.pypy.org
Tue Jun 12 11:33:50 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: linux-only
Changeset: r283:a88af068780b
Date: 2012-06-12 11:01 +0200
http://bitbucket.org/cffi/cffi/changeset/a88af068780b/

Log:	Finish the (non-partial) struct verification. For now uses
	'typeof()', which is a gcc extension.

diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -84,7 +84,7 @@
         corresponding Python type: <class 'ffi.CData<...>'>.
         It can also be used on 'cdata' instance to get its C type.
         """
-        if isinstance(cdecl, (str, unicode)):
+        if isinstance(cdecl, basestring):
             try:
                 return self._parsed_types[cdecl]
             except KeyError:
@@ -99,7 +99,7 @@
         """Return the size in bytes of the argument.  It can be a
         string naming a C type, or a 'cdata' instance.
         """
-        if isinstance(cdecl, (str, unicode)):
+        if isinstance(cdecl, basestring):
             BType = self.typeof(cdecl)
             return self._backend.sizeof(BType)
         else:
@@ -109,15 +109,17 @@
         """Return the natural alignment size in bytes of the C type
         given as a string.
         """
-        BType = self.typeof(cdecl)
-        return self._backend.alignof(BType)
+        if isinstance(cdecl, basestring):
+            cdecl = self.typeof(cdecl)
+        return self._backend.alignof(cdecl)
 
     def offsetof(self, cdecl, fieldname):
         """Return the offset of the named field inside the given
         structure, which must be given as a C type name.
         """
-        BType = self.typeof(cdecl)
-        return self._backend.offsetof(BType, fieldname)
+        if isinstance(cdecl, basestring):
+            cdecl = self.typeof(cdecl)
+        return self._backend.offsetof(cdecl, fieldname)
 
     def new(self, cdecl, init=None):
         """Allocate an instance 'x' of the named C type, and return a
diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -27,7 +27,7 @@
             return self.new_backend_type(ffi, *args)
 
     def verifier_declare_typedef(self, verifier, name):
-        verifier.write('{ %s = (%s**)0; }' % (
+        verifier.write('__sametype__(%s, %s)' % (
             self.get_c_name('** result'), name))
 
 
@@ -170,19 +170,37 @@
         return ffi._backend.new_struct_type(self.name)
 
     def verifier_declare_struct(self, verifier, name):
+        assert name == self.name
         if self.partial:
-            self.verifier_decl_partial(verifier, name)
+            self.verifier_decl_partial(verifier)
         else:
-            self.verifier_decl_notpartial(verifier, name)
+            self.verifier_decl_notpartial(verifier)
 
-    def verifier_decl_notpartial(self, verifier, name):
+    def verifier_decl_notpartial(self, verifier):
         if self.fldnames is None:    # not partial, but fully opaque:
             return                   # cannot really test even for existence
         struct = verifier.ffi._get_cached_btype(self)
-        verifier.write('__sameconstant__(sizeof(struct %s), %d)' % (
-            name, verifier.ffi.sizeof(struct)))
+        verifier.write('{')
+        verifier.write('struct __aligncheck__ { char x; struct %s y; };' %
+                       self.name)
+        verifier.write(
+            '__sameconstant__(sizeof(struct %s), %d)' % (
+            self.name, verifier.ffi.sizeof(struct)))
+        verifier.write(
+            '__sameconstant__(offsetof(struct __aligncheck__, y), %d)' % (
+            verifier.ffi.alignof(struct),))
+        for fname, ftype, fbitsize in zip(self.fldnames, self.fldtypes,
+                                          self.fldbitsize):
+            if fbitsize >= 0:
+                assert 0, "XXX: bitfield"
+            verifier.write('__sameconstant__(offsetof(struct %s, %s), %d)' % (
+                self.name, fname, verifier.ffi.offsetof(struct, fname)))
+            # XXX gcc only!
+            verifier.write('__sametype__(%s, typeof(((struct %s *)0)->%s))' % (
+                ftype.get_c_name('** result'), self.name, fname))
+        verifier.write('}')
 
-    def verifier_decl_partial(self, verifier, name):
+    def verifier_decl_partial(self, verifier):
         assert self.fldnames is not None
         verifier.write('{')
         verifier.write('struct __aligncheck__ { char x; struct %s y; };' %
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -21,15 +21,19 @@
         tst_file_base = ffiplatform._get_test_file_base()
         self.has_printf = False
         with open(tst_file_base + '.c', 'w') as f:
-            f.write('#include <stdio.h>\n'
-                    '#include <stdint.h>\n'
-                    '#include <stddef.h>\n'
-                    '#include <unistd.h>\n'
-                    '\n'
-                    '#define __sameconstant__(x, y) \\\n'
-                    '  { int result[1-2*((x)-(y))*((x)-(y))]; }\n'
-                    '\n'
-                    )
+            f.write("""\
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#define __sameconstant__(x, y) \\
+  { int result[1-2*((x)-(y))*((x)-(y))]; }
+
+#define __sametype__(ppresult, typename) \\
+  { ppresult = (typename**)0; }
+
+""")
             f.write(preamble + "\n\n")
             f.write('int main() {\n')
             self.f = f


More information about the pypy-commit mailing list