Commits

Armin Rigo committed 8d37133

Start work on the structures.

  • Participants
  • Parent commits 6b77c57

Comments (0)

Files changed (3)

             backend = backend_ctypes.CTypesBackend()
         self._backend = backend
         self._functions = {}
+        self._structs = {}
         self._cached_btypes = {}
         self._cached_parsed_types = {}
         self.C = FFILibrary(self, self._backend.load_library())
                     'new_primitive_type', ident)
             #
             if isinstance(type, pycparser.c_ast.Struct):
-                xxx
+                assert type.name in self._structs, "XXX opaque structs"
+                fields = self._structs[type.name].decls
+                fnames = [decl.name for decl in fields]
+                btypes = [self._get_btype(decl.type) for decl in fields]
+                return self._backend.get_cached_btype(
+                    'new_struct_type', type.name, tuple(fnames), tuple(btypes))
         #
         raise FFIError("bad or unsupported type declaration")
 
         self.ffi = ffi
 
     def visit_FuncDecl(self, node):
-        # assume for now primitive args and result types
         name = node.type.declname
         if name in self.ffi._functions:
-            raise FFIError("multiple declaration of function %r" % (name,))
+            raise FFIError("multiple declarations of function %s" % (name,))
         self.ffi._functions[name] = node
 
     def visit_Struct(self, node):
-        xxx
+        if node.decls is not None:
+            name = node.name
+            if name in self.ffi._structs:
+                raise FFIError("multiple declarations of struct %s" % (name,))
+            self.ffi._structs[name] = node

File ffi/backend_ctypes.py

         CTypesArray._fix_class()
         return CTypesArray
 
+    def new_struct_type(self, name, fnames, BFieldTypes):
+        #
+        class struct(ctypes.Structure):
+            _fields_ = [(fname, BField._ctype)
+                        for (fname, BField) in zip(fnames, BFieldTypes)]
+        struct.__name__ = 'struct_%s' % name
+        #
+        class CTypesStruct(CTypesData):
+            _ctype = struct
+            _reftypename = 'struct %s &' % name
+
+            def __init__(self, init):
+                self._blob = struct()
+                if init is not None:
+                    xxx
+        #
+        for fname, BField in zip(fnames, BFieldTypes):
+            def getter(self, fname=fname, BField=BField):
+                return BField._from_ctypes(getattr(self._blob, fname))
+            def setter(self, value, fname=fname, BField=BField):
+                setattr(self._blob, fname, BField._to_ctypes(value))
+            setattr(CTypesStruct, fname, property(getter, setter))
+        #
+        CTypesStruct._fix_class()
+        return CTypesStruct
+
 
 class CTypesLibrary(object):
 

File testing/backend_tests.py

         assert float(f) == 1E200 * 1E200     # infinite, not enough precision
 
     def test_struct_simple(self):
-        py.test.skip("in-progress")
         ffi = FFI(backend=self.Backend())
         ffi.cdef("struct foo { int a; short b, c; };")
         s = ffi.new("struct foo")