cpython: 3fbfa61634de (original) (raw)
--- a/Lib/ctypes/test/test_bitfields.py +++ b/Lib/ctypes/test/test_bitfields.py @@ -240,5 +240,25 @@ class BitFieldTest(unittest.TestCase): anonymous = [""] fields = [("", X)]
- @unittest.skipUnless(hasattr(ctypes, "c_uint32"), "c_int32 is required")
- def test_uint32(self):
class X(Structure):[](#l1.9)
_fields_ = [("a", c_uint32, 32)][](#l1.10)
x = X()[](#l1.11)
x.a = 10[](#l1.12)
self.assertEquals(x.a, 10)[](#l1.13)
x.a = 0xFDCBA987[](#l1.14)
self.assertEquals(x.a, 0xFDCBA987)[](#l1.15)
- @unittest.skipUnless(hasattr(ctypes, "c_uint64"), "c_int64 is required")
- def test_uint64(self):
class X(Structure):[](#l1.19)
_fields_ = [("a", c_uint64, 64)][](#l1.20)
x = X()[](#l1.21)
x.a = 10[](#l1.22)
self.assertEquals(x.a, 10)[](#l1.23)
x.a = 0xFEDCBA9876543211[](#l1.24)
self.assertEquals(x.a, 0xFEDCBA9876543211)[](#l1.25)
+ if name == "main": unittest.main()
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -138,6 +138,9 @@ C API Extension Modules ----------------- +- Issue #6493: An issue in ctypes on Windows that caused structure bitfields
--- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -427,12 +427,8 @@ get_ulonglong(PyObject v, unsigned PY_L #define LOW_BIT(x) ((x) & 0xFFFF) #define NUM_BITS(x) ((x) >> 16) -/ This seems nore a compiler issue than a Windows/non-Windows one / -#ifdef MS_WIN32 -# define BIT_MASK(size) ((1 << NUM_BITS(size))-1) -#else -# define BIT_MASK(size) ((1LL << NUM_BITS(size))-1) -#endif +/ Doesn't work if NUM_BITS(size) == 0, but it never happens in SET() call. / +#define BIT_MASK(type, size) (((((type)1 << (NUM_BITS(size) - 1)) - 1) << 1) + 1) / This macro CHANGES the first parameter IN PLACE. For proper sign handling, we must first shift left, then right. @@ -444,10 +440,10 @@ get_ulonglong(PyObject v, unsigned PY_L } / This macro RETURNS the first parameter with the bit field CHANGED. */ -#define SET(x, v, size) [](#l3.22) +#define SET(type, x, v, size) [](#l3.23) (NUM_BITS(size) ? [](#l3.24)
( ( x & ~(BIT_MASK(size) << LOW_BIT(size)) ) | ( (v & BIT_MASK(size)) << LOW_BIT(size) ) ) \[](#l3.25)
: v)[](#l3.26)
( ( (type)x & ~(BIT_MASK(type, size) << LOW_BIT(size)) ) | ( ((type)v & BIT_MASK(type, size)) << LOW_BIT(size) ) ) \[](#l3.27)
: (type)v)[](#l3.28)
/* byte swapping macros */ #define SWAP_2(v) [](#l3.31) @@ -519,7 +515,7 @@ b_set(void *ptr, PyObject *value, Py_ssi long val; if (get_long(value, &val) < 0) return NULL;
@@ -538,8 +534,7 @@ B_set(void *ptr, PyObject *value, Py_ssi unsigned long val; if (get_ulong(value, &val) < 0) return NULL;
@@ -560,7 +555,7 @@ h_set(void *ptr, PyObject *value, Py_ssi if (get_long(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x));
@@ -575,7 +570,7 @@ h_set_sw(void *ptr, PyObject *value, Py_ return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_2(field);
- field = SET(short, field, val, size); field = SWAP_2(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -608,7 +603,7 @@ H_set(void *ptr, PyObject *value, Py_ssi if (get_ulong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x));
@@ -622,7 +617,7 @@ H_set_sw(void *ptr, PyObject *value, Py_ return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_2(field);
- field = SET(unsigned short, field, val, size); field = SWAP_2(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -656,7 +651,7 @@ i_set(void *ptr, PyObject *value, Py_ssi if (get_long(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x));
@@ -670,7 +665,7 @@ i_set_sw(void *ptr, PyObject *value, Py_ return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_INT(field);
- field = SET(int, field, val, size); field = SWAP_INT(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -757,7 +752,7 @@ I_set(void *ptr, PyObject *value, Py_ssi if (get_ulong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x));
@@ -770,7 +765,7 @@ I_set_sw(void *ptr, PyObject *value, Py_ if (get_ulong(value, &val) < 0) return NULL; memcpy(&field, ptr, sizeof(field));
- field = SET(unsigned int, field, (unsigned int)val, size); field = SWAP_INT(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -804,7 +799,7 @@ l_set(void *ptr, PyObject *value, Py_ssi if (get_long(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x));
@@ -818,7 +813,7 @@ l_set_sw(void *ptr, PyObject *value, Py_ return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_LONG(field);
- field = SET(long, field, val, size); field = SWAP_LONG(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -852,7 +847,7 @@ L_set(void *ptr, PyObject *value, Py_ssi if (get_ulong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x));
@@ -866,7 +861,7 @@ L_set_sw(void *ptr, PyObject *value, Py_ return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_LONG(field);
- field = SET(unsigned long, field, val, size); field = SWAP_LONG(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -901,7 +896,7 @@ q_set(void *ptr, PyObject *value, Py_ssi if (get_longlong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x));
@@ -915,7 +910,7 @@ q_set_sw(void *ptr, PyObject *value, Py_ return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_8(field);
- field = SET(PY_LONG_LONG, field, val, size); field = SWAP_8(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -948,7 +943,7 @@ Q_set(void *ptr, PyObject *value, Py_ssi if (get_ulonglong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x));
@@ -962,7 +957,7 @@ Q_set_sw(void *ptr, PyObject *value, Py_ return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_8(field);