Commit 66361219 authored by Victor Stinner's avatar Victor Stinner

Close #4376: ctypes now supports nested structures in a endian different than

the parent structure. Patch by Vlad Riscutia.
parent cb4ae815
...@@ -7,14 +7,18 @@ def _other_endian(typ): ...@@ -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):
......
...@@ -185,18 +185,32 @@ class Test(unittest.TestCase): ...@@ -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 # create nested structures with given byteorders and set memory to data
else: def set_structures(endianness, nested_endianness, data):
base = LittleEndianStructure class NestedStructure(nested_endianness):
_fields_ = [("x", c_uint32),
class T(Structure): ("y", c_uint32)]
_fields_ = [("a", c_int),
("b", c_int)] class TestStructure(endianness):
class S(base): _fields_ = [("point", NestedStructure)]
pass
self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)]) 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.
......
...@@ -735,6 +735,7 @@ Jan Pieter Riegel ...@@ -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
......
...@@ -27,6 +27,9 @@ Core and Builtins ...@@ -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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment