Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6636121

Browse files
author
Victor Stinner
committed
Close #4376: ctypes now supports nested structures in a endian different than
the parent structure. Patch by Vlad Riscutia.
1 parent cb4ae81 commit 6636121

4 files changed

Lines changed: 40 additions & 18 deletions

File tree

Lib/ctypes/_endian.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ def _other_endian(typ):
77
"""Return the type with the 'other' byte order. Simple types like
88
c_int and so on already have __ctype_be__ and __ctype_le__
99
attributes which contain the types, for more complicated types
10-
only arrays are supported.
10+
arrays and structures are supported.
1111
"""
12-
try:
12+
# check _OTHER_ENDIAN attribute (present if typ is primitive type)
13+
if hasattr(typ, _OTHER_ENDIAN):
1314
return getattr(typ, _OTHER_ENDIAN)
14-
except AttributeError:
15-
if type(typ) == _array_type:
16-
return _other_endian(typ._type_) * typ._length_
17-
raise TypeError("This type does not support other endian: %s" % typ)
15+
# if typ is array
16+
if isinstance(typ, _array_type):
17+
return _other_endian(typ._type_) * typ._length_
18+
# if typ is structure
19+
if issubclass(typ, Structure):
20+
return typ
21+
raise TypeError("This type does not support other endian: %s" % typ)
1822

1923
class _swapped_meta(type(Structure)):
2024
def __setattr__(self, attrname, value):

Lib/ctypes/test/test_byteswap.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -185,18 +185,32 @@ class T(base):
185185
self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)])
186186

187187
def test_struct_struct(self):
188-
# Nested structures with different byte order not (yet) supported
189-
if sys.byteorder == "little":
190-
base = BigEndianStructure
191-
else:
192-
base = LittleEndianStructure
193-
194-
class T(Structure):
195-
_fields_ = [("a", c_int),
196-
("b", c_int)]
197-
class S(base):
198-
pass
199-
self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)])
188+
# nested structures with different byteorders
189+
190+
# create nested structures with given byteorders and set memory to data
191+
def set_structures(endianness, nested_endianness, data):
192+
class NestedStructure(nested_endianness):
193+
_fields_ = [("x", c_uint32),
194+
("y", c_uint32)]
195+
196+
class TestStructure(endianness):
197+
_fields_ = [("point", NestedStructure)]
198+
199+
self.assertEqual(len(data), sizeof(TestStructure))
200+
return cast(data, POINTER(TestStructure))[0]
201+
202+
for nested, data in (
203+
(BigEndianStructure, b'\0\0\0\1\0\0\0\2'),
204+
(LittleEndianStructure, b'\1\0\0\0\2\0\0\0'),
205+
):
206+
for parent in (
207+
BigEndianStructure,
208+
LittleEndianStructure,
209+
Structure,
210+
):
211+
s = set_structures(parent, nested, data)
212+
self.assertEqual(s.point.x, 1)
213+
self.assertEqual(s.point.y, 2)
200214

201215
def test_struct_fields_2(self):
202216
# standard packing in struct uses no alignment.

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ Jan Pieter Riegel
735735
Armin Rigo
736736
Nicholas Riley
737737
Jean-Claude Rimbault
738+
Vlad Riscutia
738739
Juan M. Bello Rivas
739740
Davide Rizzo
740741
Anthony Roach

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ Core and Builtins
2727
Library
2828
-------
2929

30+
- Issue #4376: ctypes now supports nested structures in a endian different than
31+
the parent structure. Patch by Vlad Riscutia.
32+
3033
- Raise ValueError when attempting to set the _CHUNK_SIZE attribute of a
3134
TextIOWrapper to a huge value, not TypeError.
3235

0 commit comments

Comments
 (0)