Author: Armin Rigo <[email protected]> Branch: Changeset: r94822:89ffd6dc4ce1 Date: 2018-07-07 17:47 +0200 http://bitbucket.org/pypy/pypy/changeset/89ffd6dc4ce1/
Log: update to cffi/30d95e2748ec diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO --- a/lib_pypy/cffi.egg-info/PKG-INFO +++ b/lib_pypy/cffi.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cffi -Version: 1.11.5 +Version: 1.12.0 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -4,8 +4,8 @@ from .api import FFI from .error import CDefError, FFIError, VerificationError, VerificationMissing -__version__ = "1.11.5" -__version_info__ = (1, 11, 5) +__version__ = "1.12.0" +__version_info__ = (1, 12, 0) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h --- a/lib_pypy/cffi/_embedding.h +++ b/lib_pypy/cffi/_embedding.h @@ -221,7 +221,7 @@ if (f != NULL && f != Py_None) { PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME - "\ncompiled with cffi version: 1.11.5" + "\ncompiled with cffi version: 1.12.0" "\n_cffi_backend module: ", f); modules = PyImport_GetModuleDict(); mod = PyDict_GetItemString(modules, "_cffi_backend"); diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -96,18 +96,21 @@ self.CData, self.CType = backend._get_types() self.buffer = backend.buffer - def cdef(self, csource, override=False, packed=False): + def cdef(self, csource, override=False, packed=False, pack=None): """Parse the given C source. This registers all declared functions, types, and global variables. The functions and global variables can then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'. The types can be used in 'ffi.new()' and other functions. If 'packed' is specified as True, all structs declared inside this cdef are packed, i.e. laid out without any field alignment at all. + Alternatively, 'pack' can be a small integer, and requests for + alignment greater than that are ignored (pack=1 is equivalent to + packed=True). """ - self._cdef(csource, override=override, packed=packed) + self._cdef(csource, override=override, packed=packed, pack=pack) - def embedding_api(self, csource, packed=False): - self._cdef(csource, packed=packed, dllexport=True) + def embedding_api(self, csource, packed=False, pack=None): + self._cdef(csource, packed=packed, pack=pack, dllexport=True) if self._embedding is None: self._embedding = '' diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py --- a/lib_pypy/cffi/backend_ctypes.py +++ b/lib_pypy/cffi/backend_ctypes.py @@ -730,7 +730,8 @@ return self._new_struct_or_union('union', name, ctypes.Union) def complete_struct_or_union(self, CTypesStructOrUnion, fields, tp, - totalsize=-1, totalalignment=-1, sflags=0): + totalsize=-1, totalalignment=-1, sflags=0, + pack=0): if totalsize >= 0 or totalalignment >= 0: raise NotImplementedError("the ctypes backend of CFFI does not support " "structures completed by verify(); please " @@ -751,6 +752,8 @@ bfield_types[fname] = Ellipsis if sflags & 8: struct_or_union._pack_ = 1 + elif pack: + struct_or_union._pack_ = pack struct_or_union._fields_ = cfields CTypesStructOrUnion._bfield_types = bfield_types # diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py --- a/lib_pypy/cffi/cparser.py +++ b/lib_pypy/cffi/cparser.py @@ -306,11 +306,25 @@ msg = 'parse error\n%s' % (msg,) raise CDefError(msg) - def parse(self, csource, override=False, packed=False, dllexport=False): + def parse(self, csource, override=False, packed=False, pack=None, + dllexport=False): + if packed: + if packed != True: + raise ValueError("'packed' should be False or True; use " + "'pack' to give another value") + if pack: + raise ValueError("cannot give both 'pack' and 'packed'") + pack = 1 + elif pack: + if pack & (pack - 1): + raise ValueError("'pack' must be a power of two, not %r" % + (pack,)) + else: + pack = 0 prev_options = self._options try: self._options = {'override': override, - 'packed': packed, + 'packed': pack, 'dllexport': dllexport} self._internal_parse(csource) finally: diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py --- a/lib_pypy/cffi/model.py +++ b/lib_pypy/cffi/model.py @@ -342,7 +342,7 @@ fixedlayout = None completed = 0 partial = False - packed = False + packed = 0 def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None): self.name = name @@ -414,11 +414,14 @@ fldtypes = [tp.get_cached_btype(ffi, finishlist) for tp in self.fldtypes] lst = list(zip(self.fldnames, fldtypes, self.fldbitsize)) - sflags = 0 + extra_flags = () if self.packed: - sflags = 8 # SF_PACKED + if self.packed == 1: + extra_flags = (8,) # SF_PACKED + else: + extra_flags = (0, self.packed) ffi._backend.complete_struct_or_union(BType, lst, self, - -1, -1, sflags) + -1, -1, *extra_flags) # else: fldtypes = [] diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py --- a/lib_pypy/cffi/recompiler.py +++ b/lib_pypy/cffi/recompiler.py @@ -893,6 +893,12 @@ else: flags.append("_CFFI_F_CHECK_FIELDS") if tp.packed: + if tp.packed > 1: + raise NotImplementedError( + "%r is declared with 'pack=%r'; only 0 or 1 are " + "supported in API mode (try to use \"...;\", which " + "does not require a 'pack' declaration)" % + (tp, tp.packed)) flags.append("_CFFI_F_PACKED") else: flags.append("_CFFI_F_EXTERNAL") diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -3,7 +3,7 @@ from rpython.rlib import rdynload, clibffi from rpython.rtyper.lltypesystem import rffi -VERSION = "1.11.5" +VERSION = "1.12.0" FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI try: diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py --- a/pypy/module/_cffi_backend/newtype.py +++ b/pypy/module/_cffi_backend/newtype.py @@ -258,6 +258,11 @@ SF_PACKED = 0x08 SF_STD_FIELD_POS = 0x80 +if sys.platform == 'win32': + SF_DEFAULT_PACKING = 8 +else: + SF_DEFAULT_PACKING = 0x40000000 # a huge power of two + if sys.platform == 'win32': DEFAULT_SFLAGS_PLATFORM = SF_MSVC_BITFIELDS @@ -309,10 +314,18 @@ w_ctype._custom_field_pos = True @unwrap_spec(w_ctype=ctypeobj.W_CType, totalsize=int, totalalignment=int, - sflags=int) + sflags=int, pack=int) def complete_struct_or_union(space, w_ctype, w_fields, w_ignored=None, - totalsize=-1, totalalignment=-1, sflags=0): + totalsize=-1, totalalignment=-1, sflags=0, + pack=0): sflags = complete_sflags(sflags) + if sflags & SF_PACKED: + pack = 1 + elif pack <= 0: + pack = SF_DEFAULT_PACKING + else: + sflags |= SF_PACKED + if (not isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion) or w_ctype.size >= 0): raise oefmt(space.w_TypeError, @@ -362,7 +375,7 @@ # update the total alignment requirement, but skip it if the # field is an anonymous bitfield or if SF_PACKED falignorg = ftype.alignof() - falign = 1 if sflags & SF_PACKED else falignorg + falign = min(pack, falignorg) do_align = True if (sflags & SF_GCC_ARM_BITFIELDS) == 0 and fbitsize >= 0: if (sflags & SF_MSVC_BITFIELDS) == 0: diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -1,7 +1,7 @@ # ____________________________________________________________ import sys -assert __version__ == "1.11.5", ("This test_c.py file is for testing a version" +assert __version__ == "1.12.0", ("This test_c.py file is for testing a version" " of cffi that differs from the one that we" " get from 'import _cffi_backend'") if sys.version_info < (3,): @@ -3541,30 +3541,50 @@ BLong = new_primitive_type("long") BChar = new_primitive_type("char") BShort = new_primitive_type("short") - BStruct = new_struct_type("struct foo") - complete_struct_or_union(BStruct, [('a1', BLong, -1), - ('a2', BChar, -1), - ('a3', BShort, -1)], - None, -1, -1, SF_PACKED) - d = BStruct.fields - assert len(d) == 3 - assert d[0][0] == 'a1' - assert d[0][1].type is BLong + for extra_args in [(SF_PACKED,), (0, 1)]: + BStruct = new_struct_type("struct foo") + complete_struct_or_union(BStruct, [('a1', BLong, -1), + ('a2', BChar, -1), + ('a3', BShort, -1)], + None, -1, -1, *extra_args) + d = BStruct.fields + assert len(d) == 3 + assert d[0][0] == 'a1' + assert d[0][1].type is BLong + assert d[0][1].offset == 0 + assert d[0][1].bitshift == -1 + assert d[0][1].bitsize == -1 + assert d[1][0] == 'a2' + assert d[1][1].type is BChar + assert d[1][1].offset == sizeof(BLong) + assert d[1][1].bitshift == -1 + assert d[1][1].bitsize == -1 + assert d[2][0] == 'a3' + assert d[2][1].type is BShort + assert d[2][1].offset == sizeof(BLong) + sizeof(BChar) + assert d[2][1].bitshift == -1 + assert d[2][1].bitsize == -1 + assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort) + assert alignof(BStruct) == 1 + # + BStruct2 = new_struct_type("struct foo") + complete_struct_or_union(BStruct2, [('b1', BChar, -1), + ('b2', BLong, -1)], + None, -1, -1, 0, 2) + d = BStruct2.fields + assert len(d) == 2 + assert d[0][0] == 'b1' + assert d[0][1].type is BChar assert d[0][1].offset == 0 assert d[0][1].bitshift == -1 assert d[0][1].bitsize == -1 - assert d[1][0] == 'a2' - assert d[1][1].type is BChar - assert d[1][1].offset == sizeof(BLong) + assert d[1][0] == 'b2' + assert d[1][1].type is BLong + assert d[1][1].offset == 2 assert d[1][1].bitshift == -1 assert d[1][1].bitsize == -1 - assert d[2][0] == 'a3' - assert d[2][1].type is BShort - assert d[2][1].offset == sizeof(BLong) + sizeof(BChar) - assert d[2][1].bitshift == -1 - assert d[2][1].bitsize == -1 - assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort) - assert alignof(BStruct) == 1 + assert sizeof(BStruct2) == 2 + sizeof(BLong) + assert alignof(BStruct2) == 2 def test_packed_with_bitfields(): if sys.platform == "win32": @@ -3915,7 +3935,7 @@ def test_char_pointer_conversion(): import warnings - assert __version__.startswith(("1.8", "1.9", "1.10", "1.11")), ( + assert __version__.startswith(("1.8", "1.9", "1.10", "1.11", "1.12")), ( "consider turning the warning into an error") BCharP = new_pointer_type(new_primitive_type("char")) BIntP = new_pointer_type(new_primitive_type("int")) diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py @@ -1824,19 +1824,39 @@ ffi = FFI(backend=self.Backend()) ffi.cdef("struct nonpacked { char a; int b; };") ffi.cdef("struct is_packed { char a; int b; };", packed=True) + ffi.cdef("struct is_packed1 { char a; int b; };", pack=1) + ffi.cdef("struct is_packed2 { char a; int b; };", pack=2) + ffi.cdef("struct is_packed4 { char a; int b; };", pack=4) + ffi.cdef("struct is_packed8 { char a; int b; };", pack=8) assert ffi.sizeof("struct nonpacked") == 8 assert ffi.sizeof("struct is_packed") == 5 + assert ffi.sizeof("struct is_packed1") == 5 + assert ffi.sizeof("struct is_packed2") == 6 + assert ffi.sizeof("struct is_packed4") == 8 + assert ffi.sizeof("struct is_packed8") == 8 assert ffi.alignof("struct nonpacked") == 4 assert ffi.alignof("struct is_packed") == 1 - s = ffi.new("struct is_packed[2]") - s[0].b = 42623381 - s[0].a = b'X' - s[1].b = -4892220 - s[1].a = b'Y' - assert s[0].b == 42623381 - assert s[0].a == b'X' - assert s[1].b == -4892220 - assert s[1].a == b'Y' + assert ffi.alignof("struct is_packed1") == 1 + assert ffi.alignof("struct is_packed2") == 2 + assert ffi.alignof("struct is_packed4") == 4 + assert ffi.alignof("struct is_packed8") == 4 + for name in ['is_packed', 'is_packed1', 'is_packed2', + 'is_packed4', 'is_packed8']: + s = ffi.new("struct %s[2]" % name) + s[0].b = 42623381 + s[0].a = b'X' + s[1].b = -4892220 + s[1].a = b'Y' + assert s[0].b == 42623381 + assert s[0].a == b'X' + assert s[1].b == -4892220 + assert s[1].a == b'Y' + + def test_pack_valueerror(self): + ffi = FFI(backend=self.Backend()) + py.test.raises(ValueError, ffi.cdef, "", pack=3) + py.test.raises(ValueError, ffi.cdef, "", packed=2) + py.test.raises(ValueError, ffi.cdef, "", packed=True, pack=1) def test_define_integer_constant(self): ffi = FFI(backend=self.Backend()) diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py @@ -2243,6 +2243,12 @@ "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()" "+ffibuilder.set_source() and not taking a final '...' argument)") +def test_pack_not_supported(): + ffi = FFI() + ffi.cdef("""struct foo { char y; int x; };""", pack=2) + py.test.raises(NotImplementedError, verify, + ffi, "test_pack_not_supported", "") + def test_gcc_visibility_hidden(): if sys.platform == 'win32': py.test.skip("test for gcc/clang") _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
