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:43:18 +02:00
parent cb4ae815b5
commit 6636121950
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 """Return the type with the 'other' byte order. Simple types like
c_int and so on already have __ctype_be__ and __ctype_le__ c_int and so on already have __ctype_be__ and __ctype_le__
attributes which contain the types, for more complicated types 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) return getattr(typ, _OTHER_ENDIAN)
except AttributeError: # if typ is array
if type(typ) == _array_type: if isinstance(typ, _array_type):
return _other_endian(typ._type_) * typ._length_ return _other_endian(typ._type_) * typ._length_
raise TypeError("This type does not support other endian: %s" % typ) # 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)): class _swapped_meta(type(Structure)):
def __setattr__(self, attrname, value): def __setattr__(self, attrname, value):

View File

@ -185,18 +185,32 @@ class Test(unittest.TestCase):
self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)]) self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)])
def test_struct_struct(self): def test_struct_struct(self):
# Nested structures with different byte order not (yet) supported # nested structures with different byteorders
if sys.byteorder == "little":
base = BigEndianStructure
else:
base = LittleEndianStructure
class T(Structure): # create nested structures with given byteorders and set memory to data
_fields_ = [("a", c_int), def set_structures(endianness, nested_endianness, data):
("b", c_int)] class NestedStructure(nested_endianness):
class S(base): _fields_ = [("x", c_uint32),
pass ("y", c_uint32)]
self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)])
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): def test_struct_fields_2(self):
# standard packing in struct uses no alignment. # standard packing in struct uses no alignment.

View File

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

View File

@ -27,6 +27,9 @@ Core and Builtins
Library 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 - Raise ValueError when attempting to set the _CHUNK_SIZE attribute of a
TextIOWrapper to a huge value, not TypeError. TextIOWrapper to a huge value, not TypeError.