Armin Rigo avatar Armin Rigo committed 9391831

Support nested anonymous structs in the front-end part.

Comments (0)

Files changed (4)

cffi/backend_ctypes.py

         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)
                 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):
             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)

testing/backend_tests.py

         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 {
             };
         """)
         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
         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())

testing/test_ctypes.py

 
     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")
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.