summaryrefslogtreecommitdiff
path: root/cffi
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2018-01-31 21:39:19 +0100
committerArmin Rigo <arigo@tunes.org>2018-01-31 21:39:19 +0100
commit0c20cb6f04a8bbae352bf71e4cab149da77f5918 (patch)
tree6569799e9f46315c0479d95cc6161bc1f7fbf1be /cffi
parent6d08968ac72990cefcb33c9efb58e68f320c6424 (diff)
downloadcffi-0c20cb6f04a8bbae352bf71e4cab149da77f5918.tar.gz
Issue #357: fix the out-of-line ABI mode when we see structs
containing anonymous unions or vice-versa
Diffstat (limited to 'cffi')
-rw-r--r--cffi/model.py17
-rw-r--r--cffi/recompiler.py9
2 files changed, 15 insertions, 11 deletions
diff --git a/cffi/model.py b/cffi/model.py
index fb30f7d..5d1139d 100644
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -352,21 +352,20 @@ class StructOrUnion(StructOrUnionOrEnum):
self.fldquals = fldquals
self.build_c_name_with_marker()
- def has_anonymous_struct_fields(self):
- if self.fldtypes is None:
- return False
- for name, type in zip(self.fldnames, self.fldtypes):
- if name == '' and isinstance(type, StructOrUnion):
- return True
- return False
+ def anonymous_struct_fields(self):
+ if self.fldtypes is not None:
+ for name, type in zip(self.fldnames, self.fldtypes):
+ if name == '' and isinstance(type, StructOrUnion):
+ yield type
- def enumfields(self):
+ def enumfields(self, expand_anonymous_struct_union=True):
fldquals = self.fldquals
if fldquals is None:
fldquals = (0,) * len(self.fldnames)
for name, type, bitsize, quals in zip(self.fldnames, self.fldtypes,
self.fldbitsize, fldquals):
- if name == '' and isinstance(type, StructOrUnion):
+ if (name == '' and isinstance(type, StructOrUnion)
+ and expand_anonymous_struct_union):
# nested anonymous struct/union
for result in type.enumfields():
yield result
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
index 821be16..f48b773 100644
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -836,6 +836,10 @@ class Recompiler:
def _struct_collecttype(self, tp):
self._do_collect_type(tp)
+ if self.target_is_python:
+ # also requires nested anon struct/unions in ABI mode, recursively
+ for fldtype in tp.anonymous_struct_fields():
+ self._struct_collecttype(fldtype)
def _struct_decl(self, tp, cname, approxname):
if tp.fldtypes is None:
@@ -884,7 +888,7 @@ class Recompiler:
named_ptr not in self.ffi._parser._included_declarations)):
if tp.fldtypes is None:
pass # opaque
- elif tp.partial or tp.has_anonymous_struct_fields():
+ elif tp.partial or any(tp.anonymous_struct_fields()):
pass # field layout obtained silently from the C compiler
else:
flags.append("_CFFI_F_CHECK_FIELDS")
@@ -896,7 +900,8 @@ class Recompiler:
flags = '|'.join(flags) or '0'
c_fields = []
if reason_for_not_expanding is None:
- enumfields = list(tp.enumfields())
+ expand_anonymous_struct_union = not self.target_is_python
+ enumfields = list(tp.enumfields(expand_anonymous_struct_union))
for fldname, fldtype, fbitsize, fqual in enumfields:
fldtype = self._field_type(tp, fldname, fldtype)
self._check_not_opaque(fldtype,