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