]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Close #4376: ctypes now supports nested structures in a endian different than
authorVictor Stinner <victor.stinner@haypocalc.com>
Wed, 13 Jul 2011 19:43:18 +0000 (21:43 +0200)
committerVictor Stinner <victor.stinner@haypocalc.com>
Wed, 13 Jul 2011 19:43:18 +0000 (21:43 +0200)
the parent structure. Patch by Vlad Riscutia.

Lib/ctypes/_endian.py
Lib/ctypes/test/test_byteswap.py
Misc/ACKS
Misc/NEWS

index b48bda5c4f20acd0002d4b98b5429351a4d505e7..721b0d1c9e3092350ebd860a6666e8e9c80cd8c6 100644 (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):
index 83cb667ed14a342ad3ae92055a3e153fab6615c1..3366ba6b286c48f2003fb718f6127e85d560722f 100644 (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
-
-        class T(Structure):
-            _fields_ = [("a", c_int),
-                        ("b", c_int)]
-        class S(base):
-            pass
-        self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)])
+        # nested structures with different byteorders
+
+        # 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.
index 625317d50a04412d70d9ba2ff241632589467c46..ee9b3734aa1e43d4ad17f337052290eec57c8fa6 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -735,6 +735,7 @@ Jan Pieter Riegel
 Armin Rigo
 Nicholas Riley
 Jean-Claude Rimbault
+Vlad Riscutia
 Juan M. Bello Rivas
 Davide Rizzo
 Anthony Roach
index 25c1f3cc67e6aa783a3b00033eface5a9968192f..caa12a61d17cd209e356d5c87dc888a68569caac 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,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.