]> granicus.if.org Git - python/commitdiff
Accessing unaligned structure fields works now on all architectures.
authorThomas Heller <theller@ctypes.org>
Mon, 20 Mar 2006 07:54:01 +0000 (07:54 +0000)
committerThomas Heller <theller@ctypes.org>
Mon, 20 Mar 2006 07:54:01 +0000 (07:54 +0000)
Including unittest.

Lib/ctypes/test/test_byteswap.py
Lib/ctypes/test/test_unaligned_structures.py [new file with mode: 0644]
Modules/_ctypes/cfield.c

index 55a264c12c460cda9569715361c05cab0f11e413..d0ada40229a5e208da911ca11d5513a8794e86b1 100644 (file)
@@ -2,7 +2,6 @@ import sys, unittest, struct, math
 from binascii import hexlify
 
 from ctypes import *
-from ctypes.test import is_resource_enabled
 
 def bin(s):
     return hexlify(buffer(s)).upper()
@@ -222,54 +221,60 @@ class Test(unittest.TestCase):
         s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
         self.failUnlessEqual(bin(s1), bin(s2))
 
-    if is_resource_enabled("unaligned_access"):
-
-        def test_unaligned_nonnative_struct_fields(self):
-            if sys.byteorder == "little":
-                base = BigEndianStructure
-                fmt = ">b h xi xd"
-            else:
-                base = LittleEndianStructure
-                fmt = "<b h xi xd"
+    def test_unaligned_nonnative_struct_fields(self):
+        if sys.byteorder == "little":
+            base = BigEndianStructure
+            fmt = ">b h xi xd"
+        else:
+            base = LittleEndianStructure
+            fmt = "<b h xi xd"
 
-            class S(base):
-                _pack_ = 1
-                _fields_ = [("b", c_byte),
+        class S(base):
+            _pack_ = 1
+            _fields_ = [("b", c_byte),
 
-                            ("h", c_short),
+                        ("h", c_short),
 
-                            ("_1", c_byte),
-                            ("i", c_int),
+                        ("_1", c_byte),
+                        ("i", c_int),
 
-                            ("_2", c_byte),
-                            ("d", c_double)]
+                        ("_2", c_byte),
+                        ("d", c_double)]
 
-            s1 = S(0x12, 0x1234, 0, 0x12345678, 0, 3.14)
-            s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
-            self.failUnlessEqual(bin(s1), bin(s2))
+        s1 = S()
+        s1.b = 0x12
+        s1.h = 0x1234
+        s1.i = 0x12345678
+        s1.d = 3.14
+        s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
+        self.failUnlessEqual(bin(s1), bin(s2))
 
-        def test_unaligned_native_struct_fields(self):
-            if sys.byteorder == "little":
-                fmt = "<b h xi xd"
-            else:
-                base = LittleEndianStructure
-                fmt = ">b h xi xd"
+    def test_unaligned_native_struct_fields(self):
+        if sys.byteorder == "little":
+            fmt = "<b h xi xd"
+        else:
+            base = LittleEndianStructure
+            fmt = ">b h xi xd"
 
-            class S(Structure):
-                _pack_ = 1
-                _fields_ = [("b", c_byte),
+        class S(Structure):
+            _pack_ = 1
+            _fields_ = [("b", c_byte),
 
-                            ("h", c_short),
+                        ("h", c_short),
 
-                            ("_1", c_byte),
-                            ("i", c_int),
+                        ("_1", c_byte),
+                        ("i", c_int),
 
-                            ("_2", c_byte),
-                            ("d", c_double)]
+                        ("_2", c_byte),
+                        ("d", c_double)]
 
-            s1 = S(0x12, 0x1234, 0, 0x12345678, 0, 3.14)
-            s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
-            self.failUnlessEqual(bin(s1), bin(s2))
+        s1 = S()
+        s1.b = 0x12
+        s1.h = 0x1234
+        s1.i = 0x12345678
+        s1.d = 3.14
+        s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
+        self.failUnlessEqual(bin(s1), bin(s2))
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Lib/ctypes/test/test_unaligned_structures.py b/Lib/ctypes/test/test_unaligned_structures.py
new file mode 100644 (file)
index 0000000..ffbc2be
--- /dev/null
@@ -0,0 +1,45 @@
+import sys, unittest\r
+from ctypes import *\r
+\r
+structures = []\r
+byteswapped_structures = []\r
+\r
+\r
+if sys.byteorder == "little":\r
+    SwappedStructure = BigEndianStructure\r
+else:\r
+    SwappedStructure = LittleEndianStructure\r
+\r
+for typ in [c_short, c_int, c_long, c_longlong,\r
+            c_float, c_double,\r
+            c_ushort, c_uint, c_ulong, c_ulonglong]:\r
+    class X(Structure):\r
+        _pack_ = 1\r
+        _fields_ = [("pad", c_byte),\r
+                    ("value", typ)]\r
+    class Y(SwappedStructure):\r
+        _pack_ = 1\r
+        _fields_ = [("pad", c_byte),\r
+                    ("value", typ)]\r
+    structures.append(X)\r
+    byteswapped_structures.append(Y)\r
+\r
+class TestStructures(unittest.TestCase):\r
+    def test_native(self):\r
+        for typ in structures:\r
+##            print typ.value\r
+            self.failUnlessEqual(typ.value.offset, 1)\r
+            o = typ()\r
+            o.value = 4\r
+            self.failUnlessEqual(o.value, 4)\r
+\r
+    def test_swapped(self):\r
+        for typ in byteswapped_structures:\r
+##            print >> sys.stderr, typ.value\r
+            self.failUnlessEqual(typ.value.offset, 1)\r
+            o = typ()\r
+            o.value = 4\r
+            self.failUnlessEqual(o.value, 4)\r
+\r
+if __name__ == '__main__':\r
+    unittest.main()\r
index 2816a6a2ab1e7fad2185fa5f602afad1d9dbd8c9..f93f9580698b6ba90f4183fab91bc80e2e126476 100644 (file)
@@ -536,9 +536,12 @@ static PyObject *
 h_set(void *ptr, PyObject *value, unsigned size)
 {
        long val;
+       short x;
        if (get_long(value, &val) < 0)
                return NULL;
-       *(short *)ptr = (short)SET(*(short *)ptr, (short)val, size);
+       memcpy(&x, ptr, sizeof(x));
+       x = SET(x, (short)val, size);
+       memcpy(ptr, &x, sizeof(x));
        _RET(value);
 }
 
@@ -550,24 +553,28 @@ h_set_sw(void *ptr, PyObject *value, unsigned size)
        short field;
        if (get_long(value, &val) < 0)
                return NULL;
-       field = SWAP_2(*(short *)ptr);
+       memcpy(&field, ptr, sizeof(field));
+       field = SWAP_2(field);
        field = SET(field, (short)val, size);
-       *(short *)ptr = SWAP_2(field);
+       field = SWAP_2(field);
+       memcpy(ptr, &field, sizeof(field));
        _RET(value);
 }
 
 static PyObject *
 h_get(void *ptr, unsigned size)
 {
-       short val = *(short *)ptr;
+       short val;
+       memcpy(&val, ptr, sizeof(val));
        GET_BITFIELD(val, size);
-       return PyInt_FromLong(val);
+       return PyInt_FromLong((long)val);
 }
 
 static PyObject *
 h_get_sw(void *ptr, unsigned size)
 {
-       short val = *(short *)ptr;
+       short val;
+       memcpy(&val, ptr, sizeof(val));
        val = SWAP_2(val);
        GET_BITFIELD(val, size);
        return PyInt_FromLong(val);
@@ -577,10 +584,12 @@ static PyObject *
 H_set(void *ptr, PyObject *value, unsigned size)
 {
        unsigned long val;
+       unsigned short x;
        if (get_ulong(value, &val) < 0)
                return NULL;
-       *(unsigned short *)ptr = (unsigned short)SET(*(unsigned short *)ptr,
-                                                    (unsigned short)val, size);
+       memcpy(&x, ptr, sizeof(x));
+       x = SET(x, (unsigned short)val, size);
+       memcpy(ptr, &x, sizeof(x));
        _RET(value);
 }
 
@@ -591,9 +600,11 @@ H_set_sw(void *ptr, PyObject *value, unsigned size)
        unsigned short field;
        if (get_ulong(value, &val) < 0)
                return NULL;
-       field = SWAP_2(*(unsigned short *)ptr);
+       memcpy(&field, ptr, sizeof(field));
+       field = SWAP_2(field);
        field = SET(field, (unsigned short)val, size);
-       *(unsigned short *)ptr = SWAP_2(field);
+       field = SWAP_2(field);
+       memcpy(ptr, &field, sizeof(field));
        _RET(value);
 }
 
@@ -601,7 +612,8 @@ H_set_sw(void *ptr, PyObject *value, unsigned size)
 static PyObject *
 H_get(void *ptr, unsigned size)
 {
-       unsigned short val = *(unsigned short *)ptr;
+       unsigned short val;
+       memcpy(&val, ptr, sizeof(val));
        GET_BITFIELD(val, size);
        return PyInt_FromLong(val);
 }
@@ -609,7 +621,8 @@ H_get(void *ptr, unsigned size)
 static PyObject *
 H_get_sw(void *ptr, unsigned size)
 {
-       unsigned short val = *(unsigned short *)ptr;
+       unsigned short val;
+       memcpy(&val, ptr, sizeof(val));
        val = SWAP_2(val);
        GET_BITFIELD(val, size);
        return PyInt_FromLong(val);
@@ -619,9 +632,12 @@ static PyObject *
 i_set(void *ptr, PyObject *value, unsigned size)
 {
        long val;
+       int x;
        if (get_long(value, &val) < 0)
                return NULL;
-       *(int *)ptr = (int)SET(*(int *)ptr, (int)val, size);
+       memcpy(&x, ptr, sizeof(x));
+       x = SET(x, (int)val, size);
+       memcpy(ptr, &x, sizeof(x));
        _RET(value);
 }
 
@@ -632,9 +648,11 @@ i_set_sw(void *ptr, PyObject *value, unsigned size)
        int field;
        if (get_long(value, &val) < 0)
                return NULL;
-       field = SWAP_INT(*(int *)ptr);
+       memcpy(&field, ptr, sizeof(field));
+       field = SWAP_INT(field);
        field = SET(field, (int)val, size);
-       *(int *)ptr = SWAP_INT(field);
+       field = SWAP_INT(field);
+       memcpy(ptr, &field, sizeof(field));
        _RET(value);
 }
 
@@ -642,7 +660,8 @@ i_set_sw(void *ptr, PyObject *value, unsigned size)
 static PyObject *
 i_get(void *ptr, unsigned size)
 {
-       int val = *(int *)ptr;
+       int val;
+       memcpy(&val, ptr, sizeof(val));
        GET_BITFIELD(val, size);
        return PyInt_FromLong(val);
 }
@@ -650,7 +669,8 @@ i_get(void *ptr, unsigned size)
 static PyObject *
 i_get_sw(void *ptr, unsigned size)
 {
-       int val = *(int *)ptr;
+       int val;
+       memcpy(&val, ptr, sizeof(val));
        val = SWAP_INT(val);
        GET_BITFIELD(val, size);
        return PyInt_FromLong(val);
@@ -684,9 +704,12 @@ static PyObject *
 I_set(void *ptr, PyObject *value, unsigned size)
 {
        unsigned long val;
+       unsigned int x;
        if (get_ulong(value, &val) < 0)
                return  NULL;
-       *(unsigned int *)ptr = (unsigned int)SET(*(unsigned int *)ptr, (unsigned int)val, size);
+       memcpy(&x, ptr, sizeof(x));
+       x = SET(x, (unsigned int)val, size);
+       memcpy(ptr, &x, sizeof(x));
        _RET(value);
 }
 
@@ -697,9 +720,10 @@ I_set_sw(void *ptr, PyObject *value, unsigned size)
        unsigned int field;
        if (get_ulong(value, &val) < 0)
                return  NULL;
-       field = SWAP_INT(*(unsigned int *)ptr);
+       memcpy(&field, ptr, sizeof(field));
        field = (unsigned int)SET(field, (unsigned int)val, size);
-       *(unsigned int *)ptr = SWAP_INT(field);
+       field = SWAP_INT(field);
+       memcpy(ptr, &field, sizeof(field));
        _RET(value);
 }
 
@@ -707,7 +731,8 @@ I_set_sw(void *ptr, PyObject *value, unsigned size)
 static PyObject *
 I_get(void *ptr, unsigned size)
 {
-       unsigned int val = *(unsigned int *)ptr;
+       unsigned int val;
+       memcpy(&val, ptr, sizeof(val));
        GET_BITFIELD(val, size);
        return PyLong_FromUnsignedLong(val);
 }
@@ -715,7 +740,8 @@ I_get(void *ptr, unsigned size)
 static PyObject *
 I_get_sw(void *ptr, unsigned size)
 {
-       unsigned int val = *(unsigned int *)ptr;
+       unsigned int val;
+       memcpy(&val, ptr, sizeof(val));
        val = SWAP_INT(val);
        GET_BITFIELD(val, size);
        return PyLong_FromUnsignedLong(val);
@@ -725,9 +751,12 @@ static PyObject *
 l_set(void *ptr, PyObject *value, unsigned size)
 {
        long val;
+       long x;
        if (get_long(value, &val) < 0)
                return NULL;
-       *(long *)ptr = (long)SET(*(long *)ptr, val, size);
+       memcpy(&x, ptr, sizeof(x));
+       x = SET(x, val, size);
+       memcpy(ptr, &x, sizeof(x));
        _RET(value);
 }
 
@@ -738,9 +767,11 @@ l_set_sw(void *ptr, PyObject *value, unsigned size)
        long field;
        if (get_long(value, &val) < 0)
                return NULL;
-       field = SWAP_LONG(*(long *)ptr);
+       memcpy(&field, ptr, sizeof(field));
+       field = SWAP_LONG(field);
        field = (long)SET(field, val, size);
-       *(long *)ptr = SWAP_LONG(field);
+       field = SWAP_LONG(field);
+       memcpy(ptr, &field, sizeof(field));
        _RET(value);
 }
 
@@ -748,7 +779,8 @@ l_set_sw(void *ptr, PyObject *value, unsigned size)
 static PyObject *
 l_get(void *ptr, unsigned size)
 {
-       long val = *(long *)ptr;
+       long val;
+       memcpy(&val, ptr, sizeof(val));
        GET_BITFIELD(val, size);
        return PyInt_FromLong(val);
 }
@@ -756,7 +788,8 @@ l_get(void *ptr, unsigned size)
 static PyObject *
 l_get_sw(void *ptr, unsigned size)
 {
-       long val = *(long *)ptr;
+       long val;
+       memcpy(&val, ptr, sizeof(val));
        val = SWAP_LONG(val);
        GET_BITFIELD(val, size);
        return PyInt_FromLong(val);
@@ -766,9 +799,12 @@ static PyObject *
 L_set(void *ptr, PyObject *value, unsigned size)
 {
        unsigned long val;
+       unsigned long x;
        if (get_ulong(value, &val) < 0)
                return  NULL;
-       *(unsigned long *)ptr = (unsigned long)SET(*(unsigned long *)ptr, val, size);
+       memcpy(&x, ptr, sizeof(x));
+       x = SET(x, val, size);
+       memcpy(ptr, &x, sizeof(x));
        _RET(value);
 }
 
@@ -779,9 +815,11 @@ L_set_sw(void *ptr, PyObject *value, unsigned size)
        unsigned long field;
        if (get_ulong(value, &val) < 0)
                return  NULL;
-       field = SWAP_LONG(*(unsigned long *)ptr);
+       memcpy(&field, ptr, sizeof(field));
+       field = SWAP_LONG(field);
        field = (unsigned long)SET(field, val, size);
-       *(unsigned long *)ptr = SWAP_LONG(field);
+       field = SWAP_LONG(field);
+       memcpy(ptr, &field, sizeof(field));
        _RET(value);
 }
 
@@ -789,7 +827,8 @@ L_set_sw(void *ptr, PyObject *value, unsigned size)
 static PyObject *
 L_get(void *ptr, unsigned size)
 {
-       unsigned long val = *(unsigned long *)ptr;
+       unsigned long val;
+       memcpy(&val, ptr, sizeof(val));
        GET_BITFIELD(val, size);
        return PyLong_FromUnsignedLong(val);
 }
@@ -797,7 +836,8 @@ L_get(void *ptr, unsigned size)
 static PyObject *
 L_get_sw(void *ptr, unsigned size)
 {
-       unsigned long val = *(unsigned long *)ptr;
+       unsigned long val;
+       memcpy(&val, ptr, sizeof(val));
        val = SWAP_LONG(val);
        GET_BITFIELD(val, size);
        return PyLong_FromUnsignedLong(val);
@@ -808,9 +848,12 @@ static PyObject *
 q_set(void *ptr, PyObject *value, unsigned size)
 {
        PY_LONG_LONG val;
+       PY_LONG_LONG x;
        if (get_longlong(value, &val) < 0)
                return NULL;
-       *(PY_LONG_LONG *)ptr = (PY_LONG_LONG)SET(*(PY_LONG_LONG *)ptr, val, size);
+       memcpy(&x, ptr, sizeof(x));
+       x = SET(x, val, size);
+       memcpy(ptr, &x, sizeof(x));
        _RET(value);
 }
 
@@ -821,16 +864,19 @@ q_set_sw(void *ptr, PyObject *value, unsigned size)
        PY_LONG_LONG field;
        if (get_longlong(value, &val) < 0)
                return NULL;
-       field = SWAP_8(*(PY_LONG_LONG *)ptr);
+       memcpy(&field, ptr, sizeof(field));
+       field = SWAP_8(field);
        field = (PY_LONG_LONG)SET(field, val, size);
-       *(PY_LONG_LONG *)ptr = SWAP_8(field);
+       field = SWAP_8(field);
+       memcpy(ptr, &field, sizeof(field));
        _RET(value);
 }
 
 static PyObject *
 q_get(void *ptr, unsigned size)
 {
-       PY_LONG_LONG val = *(PY_LONG_LONG *)ptr;
+       PY_LONG_LONG val;
+       memcpy(&val, ptr, sizeof(val));
        GET_BITFIELD(val, size);
        return PyLong_FromLongLong(val);
 }
@@ -838,7 +884,8 @@ q_get(void *ptr, unsigned size)
 static PyObject *
 q_get_sw(void *ptr, unsigned size)
 {
-       PY_LONG_LONG val = *(PY_LONG_LONG *)ptr;
+       PY_LONG_LONG val;
+       memcpy(&val, ptr, sizeof(val));
        val = SWAP_8(val);
        GET_BITFIELD(val, size);
        return PyLong_FromLongLong(val);
@@ -848,9 +895,12 @@ static PyObject *
 Q_set(void *ptr, PyObject *value, unsigned size)
 {
        unsigned PY_LONG_LONG val;
+       unsigned PY_LONG_LONG x;
        if (get_ulonglong(value, &val) < 0)
                return NULL;
-       *(unsigned PY_LONG_LONG *)ptr = (unsigned PY_LONG_LONG)SET(*(unsigned PY_LONG_LONG *)ptr, val, size);
+       memcpy(&x, ptr, sizeof(x));
+       x = SET(x, val, size);
+       memcpy(ptr, &x, sizeof(x));
        _RET(value);
 }
 
@@ -861,16 +911,19 @@ Q_set_sw(void *ptr, PyObject *value, unsigned size)
        unsigned PY_LONG_LONG field;
        if (get_ulonglong(value, &val) < 0)
                return NULL;
-       field = SWAP_8(*(unsigned PY_LONG_LONG *)ptr);
+       memcpy(&field, ptr, sizeof(field));
+       field = SWAP_8(field);
        field = (unsigned PY_LONG_LONG)SET(field, val, size);
-       *(unsigned PY_LONG_LONG *)ptr = SWAP_8(field);
+       field = SWAP_8(field);
+       memcpy(ptr, &field, sizeof(field));
        _RET(value);
 }
 
 static PyObject *
 Q_get(void *ptr, unsigned size)
 {
-       unsigned PY_LONG_LONG val = *(unsigned PY_LONG_LONG *)ptr;
+       unsigned PY_LONG_LONG val;
+       memcpy(&val, ptr, sizeof(val));
        GET_BITFIELD(val, size);
        return PyLong_FromUnsignedLongLong(val);
 }
@@ -878,7 +931,8 @@ Q_get(void *ptr, unsigned size)
 static PyObject *
 Q_get_sw(void *ptr, unsigned size)
 {
-       unsigned PY_LONG_LONG val = *(unsigned PY_LONG_LONG *)ptr;
+       unsigned PY_LONG_LONG val;
+       memcpy(&val, ptr, sizeof(val));
        val = SWAP_8(val);
        GET_BITFIELD(val, size);
        return PyLong_FromUnsignedLongLong(val);
@@ -903,14 +957,16 @@ d_set(void *ptr, PyObject *value, unsigned size)
                             value->ob_type->tp_name);
                return NULL;
        }
-       *(double *)ptr = x;
+       memcpy(ptr, &x, sizeof(double));
        _RET(value);
 }
 
 static PyObject *
 d_get(void *ptr, unsigned size)
 {
-       return PyFloat_FromDouble(*(double *)ptr);
+       double val;
+       memcpy(&val, ptr, sizeof(val));
+       return PyFloat_FromDouble(val);
 }
 
 static PyObject *
@@ -957,14 +1013,16 @@ f_set(void *ptr, PyObject *value, unsigned size)
                             value->ob_type->tp_name);
                return NULL;
        }
-       *(float *)ptr = x;
+       memcpy(ptr, &x, sizeof(x));
        _RET(value);
 }
 
 static PyObject *
 f_get(void *ptr, unsigned size)
 {
-       return PyFloat_FromDouble(*(float *)ptr);
+       float val;
+       memcpy(&val, ptr, sizeof(val));
+       return PyFloat_FromDouble(val);
 }
 
 static PyObject *