Author: Armin Rigo <[email protected]>
Branch: cffi-1.0
Changeset: r77288:a9f13b92c3db
Date: 2015-05-11 07:08 +0200
http://bitbucket.org/pypy/pypy/changeset/a9f13b92c3db/

Log:    Partial test and fix, explaining the limitation

diff --git a/pypy/module/_cffi_backend/cffi_opcode.py 
b/pypy/module/_cffi_backend/cffi_opcode.py
--- a/pypy/module/_cffi_backend/cffi_opcode.py
+++ b/pypy/module/_cffi_backend/cffi_opcode.py
@@ -137,6 +137,7 @@
 F_CHECK_FIELDS  = 0x02
 F_PACKED        = 0x04
 F_EXTERNAL      = 0x08
+F_OPAQUE        = 0x10
 
 CLASS_NAME = {}
 for _name, _value in list(globals().items()):
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
@@ -231,17 +231,19 @@
     if ffi.cached_types[type_index] is not None:
         return ffi.cached_types[type_index] #found already in the "primary" 
slot
 
+    space = ffi.space
     w_ctype = None
     c_flags = rffi.getintfield(s, 'c_flags')
+    c_first_field_index = rffi.getintfield(s, 'c_first_field_index')
     if (c_flags & cffi_opcode.F_EXTERNAL) == 0:
-        space = ffi.space
         if (c_flags & cffi_opcode.F_UNION) != 0:
             name = _realize_name("union ", s.c_name)
             x = ctypestruct.W_CTypeUnion(space, name)
         else:
             name = _realize_name("struct ", s.c_name)
             x = ctypestruct.W_CTypeStruct(space, name)
-        if rffi.getintfield(s, 'c_first_field_index') >= 0:
+        if (c_flags & cffi_opcode.F_OPAQUE) == 0:
+            assert c_first_field_index >= 0
             w_ctype = x
             w_ctype.size = rffi.getintfield(s, 'c_size')
             w_ctype.alignment = rffi.getintfield(s, 'c_alignment')
@@ -249,13 +251,26 @@
             # None, making it a "lazy" (i.e. "non-forced") kind of struct
             w_ctype._lazy_ffi = ffi
             w_ctype._lazy_s = s
+        else:
+            assert c_first_field_index < 0
     else:
+        assert c_first_field_index < 0
         x = _fetch_external_struct_or_union(s, ffi.included_libs)
         if x is None:
             raise oefmt(ffi.w_FFIError,
                     "'%s %s' should come from ffi.include() but was not found",
                     "union" if c_flags & cffi_opcode.F_UNION else "struct",
                     rffi.charp2str(s.c_name))
+        assert isinstance(x, ctypestruct.W_CTypeStructOrUnion)
+        if (c_flags & cffi_opcode.F_OPAQUE) == 0 and x.size < 0:
+            prefix = "union" if c_flags & cffi_opcode.F_UNION else "struct"
+            name = rffi.charp2str(s.c_name)
+            raise oefmt(space.w_NotImplementedError,
+                    "'%s %s' is opaque in the ffi.include(), but no "
+                    "longer in the ffi doing the include (workaround: don't "
+                    "use ffi.include() but duplicate the declarations of "
+                    "everything using %s %s)",
+                    prefix, name, prefix, name)
 
     # Update the "primary" OP_STRUCT_UNION slot
     ffi.cached_types[type_index] = x
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py 
b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -614,6 +614,22 @@
         assert ffi.cast("int *", p)[0] == 42
         assert lib.ff7b(p) == 42
 
+    def test_include_8(self):
+        ffi1, lib1 = self.prepare(
+            "struct foo_s;",
+            "test_include_8_parent",
+            "struct foo_s;")
+        ffi, lib = self.prepare(
+            "struct foo_s { int x, y; };",
+            "test_include_8",
+            "struct foo_s { int x, y; };",
+            includes=[ffi1])
+        e = raises(NotImplementedError, ffi.new, "struct foo_s *")
+        assert str(e.value) == (
+            "'struct foo_s' is opaque in the ffi.include(), but no longer in "
+            "the ffi doing the include (workaround: don't use ffi.include() 
but"
+            " duplicate the declarations of everything using struct foo_s)")
+
     def test_bitfield_basic(self):
         ffi, lib = self.prepare(
             "struct bitfield { int a:10, b:25; };",
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to