diff options
author | Thomas Heller <theller@ctypes.org> | 2006-03-20 07:54:01 (GMT) |
---|---|---|
committer | Thomas Heller <theller@ctypes.org> | 2006-03-20 07:54:01 (GMT) |
commit | d59ca8f335282ca72896c936d862a9a68633d73f (patch) | |
tree | e3565e8042b2c3bb3a11c06d89580efec8581cfe | |
parent | 6c2f913805bc0c678c7947502acfea5cb0ae0c3a (diff) | |
download | cpython-d59ca8f335282ca72896c936d862a9a68633d73f.zip cpython-d59ca8f335282ca72896c936d862a9a68633d73f.tar.gz cpython-d59ca8f335282ca72896c936d862a9a68633d73f.tar.bz2 |
Accessing unaligned structure fields works now on all architectures.
Including unittest.
-rw-r--r-- | Lib/ctypes/test/test_byteswap.py | 81 | ||||
-rw-r--r-- | Lib/ctypes/test/test_unaligned_structures.py | 45 | ||||
-rw-r--r-- | Modules/_ctypes/cfield.c | 150 |
3 files changed, 192 insertions, 84 deletions
diff --git a/Lib/ctypes/test/test_byteswap.py b/Lib/ctypes/test/test_byteswap.py index 55a264c..d0ada40 100644 --- a/Lib/ctypes/test/test_byteswap.py +++ b/Lib/ctypes/test/test_byteswap.py @@ -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 index 0000000..ffbc2be --- /dev/null +++ b/Lib/ctypes/test/test_unaligned_structures.py @@ -0,0 +1,45 @@ +import sys, unittest
+from ctypes import *
+
+structures = []
+byteswapped_structures = []
+
+
+if sys.byteorder == "little":
+ SwappedStructure = BigEndianStructure
+else:
+ SwappedStructure = LittleEndianStructure
+
+for typ in [c_short, c_int, c_long, c_longlong,
+ c_float, c_double,
+ c_ushort, c_uint, c_ulong, c_ulonglong]:
+ class X(Structure):
+ _pack_ = 1
+ _fields_ = [("pad", c_byte),
+ ("value", typ)]
+ class Y(SwappedStructure):
+ _pack_ = 1
+ _fields_ = [("pad", c_byte),
+ ("value", typ)]
+ structures.append(X)
+ byteswapped_structures.append(Y)
+
+class TestStructures(unittest.TestCase):
+ def test_native(self):
+ for typ in structures:
+## print typ.value
+ self.failUnlessEqual(typ.value.offset, 1)
+ o = typ()
+ o.value = 4
+ self.failUnlessEqual(o.value, 4)
+
+ def test_swapped(self):
+ for typ in byteswapped_structures:
+## print >> sys.stderr, typ.value
+ self.failUnlessEqual(typ.value.offset, 1)
+ o = typ()
+ o.value = 4
+ self.failUnlessEqual(o.value, 4)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 2816a6a..f93f958 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -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 * |