summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2013-10-17 17:07:46 +0200
committerArmin Rigo <arigo@tunes.org>2013-10-17 17:07:46 +0200
commit4540da0cd806e184e694fa315299cacc04628e3b (patch)
tree31d69b739366a03ed85853d7ea75cfce72508336
parentd892fff022aaa3465ee61af81a4415e30f683edd (diff)
downloadcffi-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.py2
-rw-r--r--cffi/model.py19
-rw-r--r--cffi/vengine_cpy.py2
-rw-r--r--cffi/vengine_gen.py2
-rw-r--r--testing/test_verify.py30
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")