Close #4376: ctypes now supports nested structures in a endian different than
the parent structure. Patch by Vlad Riscutia.
This commit is contained in:
parent
fbe84d92ab
commit
bf547fd3f2
|
@ -10,13 +10,17 @@ 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:
|
||||
# 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)):
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -685,6 +685,7 @@ Jan Pieter Riegel
|
|||
Armin Rigo
|
||||
Nicholas Riley
|
||||
Jean-Claude Rimbault
|
||||
Vlad Riscutia
|
||||
Juan M. Bello Rivas
|
||||
Davide Rizzo
|
||||
Anthony Roach
|
||||
|
|
|
@ -30,6 +30,9 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #4376: ctypes now supports nested structures in a endian different than
|
||||
the parent structure. Patch by Vlad Riscutia.
|
||||
|
||||
- Issue #12493: subprocess: Popen.communicate() now also handles EINTR errors
|
||||
if the process has only one pipe.
|
||||
|
||||
|
|
Loading…
Reference in New Issue