[pypy-commit] cffi cffi-1.0: Partial test and fix, explaining the limitation

arigo noreply at buildbot.pypy.org
Mon May 11 07:07:42 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1964:2d930e5f6960
Date: 2015-05-11 07:08 +0200
http://bitbucket.org/cffi/cffi/changeset/2d930e5f6960/

Log:	Partial test and fix, explaining the limitation

diff --git a/_cffi1/cffi_opcode.py b/_cffi1/cffi_opcode.py
--- a/_cffi1/cffi_opcode.py
+++ b/_cffi1/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/_cffi1/parse_c_type.h b/_cffi1/parse_c_type.h
--- a/_cffi1/parse_c_type.h
+++ b/_cffi1/parse_c_type.h
@@ -97,6 +97,7 @@
                                      // "standard layout" or if some are missing
 #define _CFFI_F_PACKED        0x04   // for CHECK_FIELDS, assume a packed struct
 #define _CFFI_F_EXTERNAL      0x08   // in some other ffi.include()
+#define _CFFI_F_OPAQUE        0x10   // opaque
 
 struct _cffi_field_s {
     const char *name;
diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c
--- a/_cffi1/realize_c_type.c
+++ b/_cffi1/realize_c_type.c
@@ -326,7 +326,8 @@
             if (x == NULL)
                 return NULL;
 
-            if (s->first_field_index >= 0) {
+            if (!(s->flags & _CFFI_F_OPAQUE)) {
+                assert(s->first_field_index >= 0);
                 ct = (CTypeDescrObject *)x;
                 ct->ct_size = (Py_ssize_t)s->size;
                 ct->ct_length = s->alignment;   /* may be -1 */
@@ -334,8 +335,11 @@
                 ct->ct_flags |= CT_LAZY_FIELD_LIST;
                 ct->ct_extra = builder;
             }
+            else
+                assert(s->first_field_index < 0);
         }
         else {
+            assert(s->first_field_index < 0);
             x = _fetch_external_struct_or_union(s, builder->included_ffis, 0);
             if (x == NULL) {
                 if (!PyErr_Occurred())
@@ -345,6 +349,21 @@
                                  : "struct", s->name);
                 return NULL;
             }
+            if (!(s->flags & _CFFI_F_OPAQUE)) {
+                if (((CTypeDescrObject *)x)->ct_flags & CT_IS_OPAQUE) {
+                    const char *prefix = (s->flags & _CFFI_F_UNION) ? "union"
+                                         : "struct";
+                    PyErr_Format(PyExc_NotImplementedError,
+                                 "'%s %.200s' 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 %.200s)",
+                                 prefix, s->name, prefix, s->name);
+                    Py_DECREF(x);
+                    return NULL;
+                }
+            }
         }
 
         /* Update the "primary" OP_STRUCT_UNION slot */
diff --git a/_cffi1/recompiler.py b/_cffi1/recompiler.py
--- a/_cffi1/recompiler.py
+++ b/_cffi1/recompiler.py
@@ -561,11 +561,14 @@
         flags = []
         if isinstance(tp, model.UnionType):
             flags.append("_CFFI_F_UNION")
+        if tp.fldtypes is None:
+            flags.append("_CFFI_F_OPAQUE")
+            reason_for_not_expanding = "opaque"
         if (tp not in self.ffi._parser._included_declarations and
                 (named_ptr is None or
                  named_ptr not in self.ffi._parser._included_declarations)):
             if tp.fldtypes is None:
-                reason_for_not_expanding = "opaque"
+                pass    # opaque
             elif tp.partial or tp.has_anonymous_struct_fields():
                 pass    # field layout obtained silently from the C compiler
             else:
diff --git a/_cffi1/test_recompiler.py b/_cffi1/test_recompiler.py
--- a/_cffi1/test_recompiler.py
+++ b/_cffi1/test_recompiler.py
@@ -619,6 +619,20 @@
     assert ffi.cast("int *", p)[0] == 42
     assert lib.ff7b(p) == 42
 
+def test_include_8():
+    ffi1 = FFI()
+    ffi1.cdef("struct foo_s;")
+    verify(ffi1, "test_include_8_parent", "struct foo_s;")
+    ffi = FFI()
+    ffi.include(ffi1)
+    ffi.cdef("struct foo_s { int x, y; };")
+    verify(ffi, "test_include_8", "struct foo_s { int x, y; };")
+    e = py.test.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_unicode_libraries():
     try:
         unicode


More information about the pypy-commit mailing list