diff -r 8893fc8e885e Lib/ctypes/_endian.py --- a/Lib/ctypes/_endian.py Wed Jul 13 15:59:43 2011 +0200 +++ b/Lib/ctypes/_endian.py Wed Jul 13 08:42:35 2011 -0700 @@ -7,14 +7,18 @@ """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 type(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): diff -r 8893fc8e885e Lib/ctypes/test/test_byteswap.py --- a/Lib/ctypes/test/test_byteswap.py Wed Jul 13 15:59:43 2011 +0200 +++ b/Lib/ctypes/test/test_byteswap.py Wed Jul 13 08:42:35 2011 -0700 @@ -185,19 +185,45 @@ 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 + # return nested member value as raw integer + def set_structures(endianness, nested_endianness): + class NestedStructure(nested_endianness): + _fields_ = [("spam", c_int32)] + class TestStructure(endianness): + _fields_ = [("menu", NestedStructure)] + + struct = TestStructure() + + # set nested member to value, adjusted to system endianness + if sys.byteorder == "little": + struct.menu.spam = 0x000000FF + else: + struct.menu.spam = 0xFF000000 + + # return structure cast to int + return cast(pointer(struct), POINTER(c_int32))[0] + + # value should be in big endian format + self.assertEqual(set_structures(BigEndianStructure, BigEndianStructure), + c_int32(0xFF000000).value) + + # value should be in little endian format + self.assertEqual(set_structures(BigEndianStructure, LittleEndianStructure), + c_int32(0x000000FF).value) + + # value should be in big endian format + self.assertEqual(set_structures(LittleEndianStructure, BigEndianStructure), + c_int32(0xFF000000).value) + + # value should be in little endian format + self.assertEqual(set_structures(LittleEndianStructure, LittleEndianStructure), + c_int32(0x000000FF).value) + + def test_struct_fields_2(self): # standard packing in struct uses no alignment. # So, we have to align using pad bytes.