[pypy-commit] cffi default: Support nested anonymous structs in the front-end part.

arigo noreply at buildbot.pypy.org
Thu Aug 23 18:17:55 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r884:9391831aab8e
Date: 2012-08-23 17:07 +0200
http://bitbucket.org/cffi/cffi/changeset/9391831aab8e/

Log:	Support nested anonymous structs in the front-end part.

diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -742,6 +742,8 @@
         name2fieldtype = dict(zip(fnames, zip(btypes, bitfields)))
         #
         for fname, BField, bitsize in fields:
+            if fname == '':
+                raise NotImplementedError("nested anonymous structs/unions")
             if hasattr(CTypesStructOrUnion, fname):
                 raise ValueError("the field name %r conflicts in "
                                  "the ctypes backend" % fname)
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -253,6 +253,12 @@
                 result = result.as_function_pointer()
             return result
         #
+        # nested anonymous structs or unions end up here
+        if isinstance(typenode, pycparser.c_ast.Struct):
+            return self._get_struct_union_enum_type('struct', typenode, name)
+        if isinstance(typenode, pycparser.c_ast.Union):
+            return self._get_struct_union_enum_type('union', typenode, name)
+        #
         raise api.FFIError("bad or unsupported type declaration")
 
     def _parse_function_type(self, typenode, funcname=None):
@@ -384,7 +390,7 @@
             type = self._get_type(decl.type, partial_length_ok=True)
             if self._partial_length:
                 self._make_partial(tp)
-            fldnames.append(decl.name)
+            fldnames.append(decl.name or '')
             fldtypes.append(type)
             fldbitsize.append(bitsize)
         tp.fldnames = tuple(fldnames)
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -1297,7 +1297,6 @@
         assert ffi.string(e) == "AA"     # pick the first one arbitrarily
 
     def test_nested_anonymous_struct(self):
-        py.test.skip("later")
         ffi = FFI(backend=self.Backend())
         ffi.cdef("""
             struct foo_s {
@@ -1306,9 +1305,9 @@
             };
         """)
         assert ffi.sizeof("struct foo_s") == 3 * SIZE_OF_INT
-        p = ffi.new("struct foo_s *", [[1], [3]])
+        p = ffi.new("struct foo_s *", [1, 2, 3])
         assert p.a == 1
-        assert p.b == 0
+        assert p.b == 2
         assert p.c == 3
         assert p.d == 3
         p.d = 17
@@ -1318,6 +1317,47 @@
         assert p.b == 19
         assert p.c == 17
         assert p.d == 17
+        p = ffi.new("struct foo_s *", {'b': 12, 'd': 14})
+        assert p.a == 0
+        assert p.b == 12
+        assert p.c == 14
+        assert p.d == 14
+
+    def test_nested_anonymous_union(self):
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""
+            union foo_u {
+                struct { int a, b; };
+                union { int c, d; };
+            };
+        """)
+        assert ffi.sizeof("union foo_u") == 2 * SIZE_OF_INT
+        p = ffi.new("union foo_u *", [5])
+        assert p.a == 5
+        assert p.b == 0
+        assert p.c == 5
+        assert p.d == 5
+        p.d = 17
+        assert p.c == 17
+        assert p.a == 17
+        p.b = 19
+        assert p.a == 17
+        assert p.b == 19
+        assert p.c == 17
+        assert p.d == 17
+        p = ffi.new("union foo_u *", {'d': 14})
+        assert p.a == 14
+        assert p.b == 0
+        assert p.c == 14
+        assert p.d == 14
+        p = ffi.new("union foo_u *", {'b': 12})
+        assert p.a == 0
+        assert p.b == 12
+        assert p.c == 0
+        assert p.d == 0
+        # we cannot specify several items in the dict, even though
+        # in theory in this particular case it would make sense
+        # to give both 'a' and 'b'
 
     def test_cast_to_array_type(self):
         ffi = FFI(backend=self.Backend())
diff --git a/testing/test_ctypes.py b/testing/test_ctypes.py
--- a/testing/test_ctypes.py
+++ b/testing/test_ctypes.py
@@ -24,3 +24,9 @@
 
     def test_cast_to_array_type(self):
         py.test.skip("ctypes backend: not supported: casting to array")
+
+    def test_nested_anonymous_struct(self):
+        py.test.skip("ctypes backend: not supported: nested anonymous struct")
+
+    def test_nested_anonymous_union(self):
+        py.test.skip("ctypes backend: not supported: nested anonymous union")


More information about the pypy-commit mailing list