diff options
author | Armin Rigo <arigo@tunes.org> | 2012-06-12 11:01:30 +0200 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2012-06-12 11:01:30 +0200 |
commit | 8109c74dce4e9a95d63b15960978fc7311090681 (patch) | |
tree | 5d5c01cfa7569cf1ba7d4a10bdcbc603378c5d7a | |
parent | 837dde02d3ca8bba8c31b7e76883be98fac9943e (diff) | |
download | cffi-linux-only.tar.gz |
Finish the (non-partial) struct verification. For now useslinux-only
'typeof()', which is a gcc extension.
-rw-r--r-- | cffi/api.py | 14 | ||||
-rw-r--r-- | cffi/model.py | 32 | ||||
-rw-r--r-- | cffi/verifier.py | 22 |
3 files changed, 46 insertions, 22 deletions
diff --git a/cffi/api.py b/cffi/api.py index eca2d9b..dbd2dda 100644 --- a/cffi/api.py +++ b/cffi/api.py @@ -84,7 +84,7 @@ class FFI(object): corresponding Python type: <class 'ffi.CData<...>'>. It can also be used on 'cdata' instance to get its C type. """ - if isinstance(cdecl, (str, unicode)): + if isinstance(cdecl, basestring): try: return self._parsed_types[cdecl] except KeyError: @@ -99,7 +99,7 @@ class FFI(object): """Return the size in bytes of the argument. It can be a string naming a C type, or a 'cdata' instance. """ - if isinstance(cdecl, (str, unicode)): + if isinstance(cdecl, basestring): BType = self.typeof(cdecl) return self._backend.sizeof(BType) else: @@ -109,15 +109,17 @@ class FFI(object): """Return the natural alignment size in bytes of the C type given as a string. """ - BType = self.typeof(cdecl) - return self._backend.alignof(BType) + if isinstance(cdecl, basestring): + cdecl = self.typeof(cdecl) + return self._backend.alignof(cdecl) def offsetof(self, cdecl, fieldname): """Return the offset of the named field inside the given structure, which must be given as a C type name. """ - BType = self.typeof(cdecl) - return self._backend.offsetof(BType, fieldname) + if isinstance(cdecl, basestring): + cdecl = self.typeof(cdecl) + return self._backend.offsetof(cdecl, fieldname) def new(self, cdecl, init=None): """Allocate an instance 'x' of the named C type, and return a diff --git a/cffi/model.py b/cffi/model.py index 6df380a..a87f3f0 100644 --- a/cffi/model.py +++ b/cffi/model.py @@ -27,7 +27,7 @@ class BaseType(object): return self.new_backend_type(ffi, *args) def verifier_declare_typedef(self, verifier, name): - verifier.write('{ %s = (%s**)0; }' % ( + verifier.write('__sametype__(%s, %s)' % ( self.get_c_name('** result'), name)) @@ -170,19 +170,37 @@ class StructType(StructOrUnion): return ffi._backend.new_struct_type(self.name) def verifier_declare_struct(self, verifier, name): + assert name == self.name if self.partial: - self.verifier_decl_partial(verifier, name) + self.verifier_decl_partial(verifier) else: - self.verifier_decl_notpartial(verifier, name) + self.verifier_decl_notpartial(verifier) - def verifier_decl_notpartial(self, verifier, name): + def verifier_decl_notpartial(self, verifier): if self.fldnames is None: # not partial, but fully opaque: return # cannot really test even for existence struct = verifier.ffi._get_cached_btype(self) - verifier.write('__sameconstant__(sizeof(struct %s), %d)' % ( - name, verifier.ffi.sizeof(struct))) + verifier.write('{') + verifier.write('struct __aligncheck__ { char x; struct %s y; };' % + self.name) + verifier.write( + '__sameconstant__(sizeof(struct %s), %d)' % ( + self.name, verifier.ffi.sizeof(struct))) + verifier.write( + '__sameconstant__(offsetof(struct __aligncheck__, y), %d)' % ( + verifier.ffi.alignof(struct),)) + for fname, ftype, fbitsize in zip(self.fldnames, self.fldtypes, + self.fldbitsize): + if fbitsize >= 0: + assert 0, "XXX: bitfield" + verifier.write('__sameconstant__(offsetof(struct %s, %s), %d)' % ( + self.name, fname, verifier.ffi.offsetof(struct, fname))) + # XXX gcc only! + verifier.write('__sametype__(%s, typeof(((struct %s *)0)->%s))' % ( + ftype.get_c_name('** result'), self.name, fname)) + verifier.write('}') - def verifier_decl_partial(self, verifier, name): + def verifier_decl_partial(self, verifier): assert self.fldnames is not None verifier.write('{') verifier.write('struct __aligncheck__ { char x; struct %s y; };' % diff --git a/cffi/verifier.py b/cffi/verifier.py index 97fe2be..353890d 100644 --- a/cffi/verifier.py +++ b/cffi/verifier.py @@ -21,15 +21,19 @@ class Verifier(object): tst_file_base = ffiplatform._get_test_file_base() self.has_printf = False with open(tst_file_base + '.c', 'w') as f: - f.write('#include <stdio.h>\n' - '#include <stdint.h>\n' - '#include <stddef.h>\n' - '#include <unistd.h>\n' - '\n' - '#define __sameconstant__(x, y) \\\n' - ' { int result[1-2*((x)-(y))*((x)-(y))]; }\n' - '\n' - ) + f.write("""\ +#include <stdio.h> +#include <stdint.h> +#include <stddef.h> +#include <unistd.h> + +#define __sameconstant__(x, y) \\ + { int result[1-2*((x)-(y))*((x)-(y))]; } + +#define __sametype__(ppresult, typename) \\ + { ppresult = (typename**)0; } + +""") f.write(preamble + "\n\n") f.write('int main() {\n') self.f = f |