diff options
author | Armin Rigo <arigo@tunes.org> | 2013-10-17 17:07:46 +0200 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2013-10-17 17:07:46 +0200 |
commit | 4540da0cd806e184e694fa315299cacc04628e3b (patch) | |
tree | 31d69b739366a03ed85853d7ea75cfce72508336 | |
parent | d892fff022aaa3465ee61af81a4415e30f683edd (diff) | |
download | cffi-4540da0cd806e184e694fa315299cacc04628e3b.tar.gz |
Support partial unions in a way very similar to partial structs.
Needed for a python-cffi mail.
-rw-r--r-- | cffi/cparser.py | 2 | ||||
-rw-r--r-- | cffi/model.py | 19 | ||||
-rw-r--r-- | cffi/vengine_cpy.py | 2 | ||||
-rw-r--r-- | cffi/vengine_gen.py | 2 | ||||
-rw-r--r-- | testing/test_verify.py | 30 |
5 files changed, 40 insertions, 15 deletions
diff --git a/cffi/cparser.py b/cffi/cparser.py index 6c248b3..1048934 100644 --- a/cffi/cparser.py +++ b/cffi/cparser.py @@ -488,7 +488,7 @@ class Parser(object): return tp def _make_partial(self, tp, nested): - if not isinstance(tp, model.StructType): + if not isinstance(tp, model.StructOrUnion): raise api.CDefError("%s cannot be partial" % (tp,)) if not tp.has_c_name() and not nested: raise NotImplementedError("%s is partial but has no C name" %(tp,)) diff --git a/cffi/model.py b/cffi/model.py index 2a9373f..2e989b3 100644 --- a/cffi/model.py +++ b/cffi/model.py @@ -248,6 +248,7 @@ class StructOrUnionOrEnum(BaseTypeByIdentity): class StructOrUnion(StructOrUnionOrEnum): fixedlayout = None completed = False + partial = False def __init__(self, name, fldnames, fldtypes, fldbitsize): self.name = name @@ -344,11 +345,6 @@ class StructOrUnion(StructOrUnionOrEnum): from .ffiplatform import VerificationError raise VerificationError(msg) - -class StructType(StructOrUnion): - kind = 'struct' - partial = False - def check_not_partial(self): if self.partial and self.fixedlayout is None: from . import ffiplatform @@ -357,19 +353,18 @@ class StructType(StructOrUnion): def build_backend_type(self, ffi, finishlist): self.check_not_partial() finishlist.append(self) - - return global_cache(self, ffi, 'new_struct_type', + # + return global_cache(self, ffi, 'new_%s_type' % self.kind, self.get_official_name(), key=self) +class StructType(StructOrUnion): + kind = 'struct' + + class UnionType(StructOrUnion): kind = 'union' - def build_backend_type(self, ffi, finishlist): - finishlist.append(self) - return global_cache(self, ffi, 'new_union_type', - self.get_official_name(), key=self) - class EnumType(StructOrUnionOrEnum): kind = 'enum' diff --git a/cffi/vengine_cpy.py b/cffi/vengine_cpy.py index e8f3575..bcd0e06 100644 --- a/cffi/vengine_cpy.py +++ b/cffi/vengine_cpy.py @@ -491,7 +491,7 @@ class VCPythonEngine(object): # function = getattr(module, layoutfuncname) layout = function() - if isinstance(tp, model.StructType) and tp.partial: + if isinstance(tp, model.StructOrUnion) and tp.partial: # use the function()'s sizes and offsets to guide the # layout of the struct totalsize = layout[0] diff --git a/cffi/vengine_gen.py b/cffi/vengine_gen.py index dc38bb7..24cce71 100644 --- a/cffi/vengine_gen.py +++ b/cffi/vengine_gen.py @@ -282,7 +282,7 @@ class VGenericEngine(object): if x < 0: break layout.append(x) num += 1 - if isinstance(tp, model.StructType) and tp.partial: + if isinstance(tp, model.StructOrUnion) and tp.partial: # use the function()'s sizes and offsets to guide the # layout of the struct totalsize = layout[0] diff --git a/testing/test_verify.py b/testing/test_verify.py index b88e4e8..e98c128 100644 --- a/testing/test_verify.py +++ b/testing/test_verify.py @@ -1162,6 +1162,36 @@ def test_ffi_union(): ffi.cdef("union foo_u { char x; long *z; };") ffi.verify("union foo_u { char x; int y; long *z; };") +def test_ffi_union_partial(): + ffi = FFI() + ffi.cdef("union foo_u { char x; ...; };") + ffi.verify("union foo_u { char x; int y; };") + assert ffi.sizeof("union foo_u") == 4 + +def test_ffi_union_with_partial_struct(): + ffi = FFI() + ffi.cdef("struct foo_s { int x; ...; }; union foo_u { struct foo_s s; };") + ffi.verify("struct foo_s { int a; int x; }; " + "union foo_u { char b[32]; struct foo_s s; };") + assert ffi.sizeof("struct foo_s") == 8 + assert ffi.sizeof("union foo_u") == 32 + +def test_ffi_union_partial_2(): + ffi = FFI() + ffi.cdef("typedef union { char x; ...; } u1;") + ffi.verify("typedef union { char x; int y; } u1;") + assert ffi.sizeof("u1") == 4 + +def test_ffi_union_with_partial_struct_2(): + ffi = FFI() + ffi.cdef("typedef struct { int x; ...; } s1;" + "typedef union { s1 s; } u1;") + ffi.verify("typedef struct { int a; int x; } s1; " + "typedef union { char b[32]; s1 s; } u1;") + assert ffi.sizeof("s1") == 8 + assert ffi.sizeof("u1") == 32 + assert ffi.offsetof("u1", "s") == 0 + def test_ffi_struct_packed(): if sys.platform == 'win32': py.test.skip("needs a GCC extension") |