[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