(merge 3.2) Close #4376: ctypes now supports nested structures in a endian

different than the parent structure. Patch by Vlad Riscutia.
This commit is contained in:
Victor Stinner 2011-07-13 21:45:16 +02:00
commit d93da2b952
4 changed files with 39 additions and 17 deletions

View File

@ -7,14 +7,18 @@ def _other_endian(typ):
"""Return the type with the 'other' byte order. Simple types like
c_int and so on already have __ctype_be__ and __ctype_le__
attributes which contain the types, for more complicated types
only arrays are supported.
arrays and structures are supported.
"""
try:
# check _OTHER_ENDIAN attribute (present if typ is primitive type)
if hasattr(typ, _OTHER_ENDIAN):
return getattr(typ, _OTHER_ENDIAN)
except AttributeError:
if type(typ) == _array_type:
return _other_endian(typ._type_) * typ._length_
raise TypeError("This type does not support other endian: %s" % typ)
# if typ is array
if isinstance(typ, _array_type):
return _other_endian(typ._type_) * typ._length_
# if typ is structure
if issubclass(typ, Structure):
return typ
raise TypeError("This type does not support other endian: %s" % typ)
class _swapped_meta(type(Structure)):
def __setattr__(self, attrname, value):

View File

@ -185,18 +185,32 @@ class Test(unittest.TestCase):
self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)])
def test_struct_struct(self):
# Nested structures with different byte order not (yet) supported
if sys.byteorder == "little":
base = BigEndianStructure
else:
base = LittleEndianStructure
# nested structures with different byteorders
class T(Structure):
_fields_ = [("a", c_int),
("b", c_int)]
class S(base):
pass
self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)])
# create nested structures with given byteorders and set memory to data
def set_structures(endianness, nested_endianness, data):
class NestedStructure(nested_endianness):
_fields_ = [("x", c_uint32),
("y", c_uint32)]
class TestStructure(endianness):
_fields_ = [("point", NestedStructure)]
self.assertEqual(len(data), sizeof(TestStructure))
return cast(data, POINTER(TestStructure))[0]
for nested, data in (
(BigEndianStructure, b'\0\0\0\1\0\0\0\2'),
(LittleEndianStructure, b'\1\0\0\0\2\0\0\0'),
):
for parent in (
BigEndianStructure,
LittleEndianStructure,
Structure,
):
s = set_structures(parent, nested, data)
self.assertEqual(s.point.x, 1)
self.assertEqual(s.point.y, 2)
def test_struct_fields_2(self):
# standard packing in struct uses no alignment.

View File

@ -784,6 +784,7 @@ Jan Pieter Riegel
Armin Rigo
Nicholas Riley
Jean-Claude Rimbault
Vlad Riscutia
Juan M. Bello Rivas
Davide Rizzo
Anthony Roach

View File

@ -225,6 +225,9 @@ Core and Builtins
Library
-------
- Issue #4376: ctypes now supports nested structures in a endian different than
the parent structure. Patch by Vlad Riscutia.
- Raise ValueError when attempting to set the _CHUNK_SIZE attribute of a
TextIOWrapper to a huge value, not TypeError.