Issue #6493: Fix handling of c_uint32 bitfields with width of 32 on Windows.
This commit is contained in:
commit
7506dab2e8
|
@ -240,5 +240,25 @@ class BitFieldTest(unittest.TestCase):
|
||||||
_anonymous_ = ["_"]
|
_anonymous_ = ["_"]
|
||||||
_fields_ = [("_", X)]
|
_fields_ = [("_", X)]
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(ctypes, "c_uint32"), "c_int32 is required")
|
||||||
|
def test_uint32(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_uint32, 32)]
|
||||||
|
x = X()
|
||||||
|
x.a = 10
|
||||||
|
self.assertEquals(x.a, 10)
|
||||||
|
x.a = 0xFDCBA987
|
||||||
|
self.assertEquals(x.a, 0xFDCBA987)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(ctypes, "c_uint64"), "c_int64 is required")
|
||||||
|
def test_uint64(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_uint64, 64)]
|
||||||
|
x = X()
|
||||||
|
x.a = 10
|
||||||
|
self.assertEquals(x.a, 10)
|
||||||
|
x.a = 0xFEDCBA9876543211
|
||||||
|
self.assertEquals(x.a, 0xFEDCBA9876543211)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -138,6 +138,9 @@ C API
|
||||||
Extension Modules
|
Extension Modules
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #6493: An issue in ctypes on Windows that caused structure bitfields
|
||||||
|
of type ctypes.c_uint32 and width 32 to incorrectly be set has been fixed.
|
||||||
|
|
||||||
- Issue #15194: Update libffi to the 3.0.11 release.
|
- Issue #15194: Update libffi to the 3.0.11 release.
|
||||||
|
|
||||||
Tools/Demos
|
Tools/Demos
|
||||||
|
|
|
@ -427,12 +427,8 @@ get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
|
||||||
#define LOW_BIT(x) ((x) & 0xFFFF)
|
#define LOW_BIT(x) ((x) & 0xFFFF)
|
||||||
#define NUM_BITS(x) ((x) >> 16)
|
#define NUM_BITS(x) ((x) >> 16)
|
||||||
|
|
||||||
/* This seems nore a compiler issue than a Windows/non-Windows one */
|
/* Doesn't work if NUM_BITS(size) == 0, but it never happens in SET() call. */
|
||||||
#ifdef MS_WIN32
|
#define BIT_MASK(type, size) (((((type)1 << (NUM_BITS(size) - 1)) - 1) << 1) + 1)
|
||||||
# define BIT_MASK(size) ((1 << NUM_BITS(size))-1)
|
|
||||||
#else
|
|
||||||
# define BIT_MASK(size) ((1LL << NUM_BITS(size))-1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* This macro CHANGES the first parameter IN PLACE. For proper sign handling,
|
/* This macro CHANGES the first parameter IN PLACE. For proper sign handling,
|
||||||
we must first shift left, then right.
|
we must first shift left, then right.
|
||||||
|
@ -444,10 +440,10 @@ get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This macro RETURNS the first parameter with the bit field CHANGED. */
|
/* This macro RETURNS the first parameter with the bit field CHANGED. */
|
||||||
#define SET(x, v, size) \
|
#define SET(type, x, v, size) \
|
||||||
(NUM_BITS(size) ? \
|
(NUM_BITS(size) ? \
|
||||||
( ( x & ~(BIT_MASK(size) << LOW_BIT(size)) ) | ( (v & BIT_MASK(size)) << LOW_BIT(size) ) ) \
|
( ( (type)x & ~(BIT_MASK(type, size) << LOW_BIT(size)) ) | ( ((type)v & BIT_MASK(type, size)) << LOW_BIT(size) ) ) \
|
||||||
: v)
|
: (type)v)
|
||||||
|
|
||||||
/* byte swapping macros */
|
/* byte swapping macros */
|
||||||
#define SWAP_2(v) \
|
#define SWAP_2(v) \
|
||||||
|
@ -519,7 +515,7 @@ b_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
long val;
|
long val;
|
||||||
if (get_long(value, &val) < 0)
|
if (get_long(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
*(signed char *)ptr = (signed char)SET(*(signed char *)ptr, (signed char)val, size);
|
*(signed char *)ptr = SET(signed char, *(signed char *)ptr, val, size);
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,8 +534,7 @@ B_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
if (get_ulong(value, &val) < 0)
|
if (get_ulong(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
*(unsigned char *)ptr = (unsigned char)SET(*(unsigned char*)ptr,
|
*(unsigned char *)ptr = SET(unsigned char, *(unsigned char*)ptr, val, size);
|
||||||
(unsigned short)val, size);
|
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,7 +555,7 @@ h_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
if (get_long(value, &val) < 0)
|
if (get_long(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&x, ptr, sizeof(x));
|
memcpy(&x, ptr, sizeof(x));
|
||||||
x = SET(x, (short)val, size);
|
x = SET(short, x, val, size);
|
||||||
memcpy(ptr, &x, sizeof(x));
|
memcpy(ptr, &x, sizeof(x));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
@ -575,7 +570,7 @@ h_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&field, ptr, sizeof(field));
|
memcpy(&field, ptr, sizeof(field));
|
||||||
field = SWAP_2(field);
|
field = SWAP_2(field);
|
||||||
field = SET(field, (short)val, size);
|
field = SET(short, field, val, size);
|
||||||
field = SWAP_2(field);
|
field = SWAP_2(field);
|
||||||
memcpy(ptr, &field, sizeof(field));
|
memcpy(ptr, &field, sizeof(field));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
|
@ -608,7 +603,7 @@ H_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
if (get_ulong(value, &val) < 0)
|
if (get_ulong(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&x, ptr, sizeof(x));
|
memcpy(&x, ptr, sizeof(x));
|
||||||
x = SET(x, (unsigned short)val, size);
|
x = SET(unsigned short, x, val, size);
|
||||||
memcpy(ptr, &x, sizeof(x));
|
memcpy(ptr, &x, sizeof(x));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
@ -622,7 +617,7 @@ H_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&field, ptr, sizeof(field));
|
memcpy(&field, ptr, sizeof(field));
|
||||||
field = SWAP_2(field);
|
field = SWAP_2(field);
|
||||||
field = SET(field, (unsigned short)val, size);
|
field = SET(unsigned short, field, val, size);
|
||||||
field = SWAP_2(field);
|
field = SWAP_2(field);
|
||||||
memcpy(ptr, &field, sizeof(field));
|
memcpy(ptr, &field, sizeof(field));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
|
@ -656,7 +651,7 @@ i_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
if (get_long(value, &val) < 0)
|
if (get_long(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&x, ptr, sizeof(x));
|
memcpy(&x, ptr, sizeof(x));
|
||||||
x = SET(x, (int)val, size);
|
x = SET(int, x, val, size);
|
||||||
memcpy(ptr, &x, sizeof(x));
|
memcpy(ptr, &x, sizeof(x));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
@ -670,7 +665,7 @@ i_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&field, ptr, sizeof(field));
|
memcpy(&field, ptr, sizeof(field));
|
||||||
field = SWAP_INT(field);
|
field = SWAP_INT(field);
|
||||||
field = SET(field, (int)val, size);
|
field = SET(int, field, val, size);
|
||||||
field = SWAP_INT(field);
|
field = SWAP_INT(field);
|
||||||
memcpy(ptr, &field, sizeof(field));
|
memcpy(ptr, &field, sizeof(field));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
|
@ -757,7 +752,7 @@ I_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
if (get_ulong(value, &val) < 0)
|
if (get_ulong(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&x, ptr, sizeof(x));
|
memcpy(&x, ptr, sizeof(x));
|
||||||
x = SET(x, (unsigned int)val, size);
|
x = SET(unsigned int, x, val, size);
|
||||||
memcpy(ptr, &x, sizeof(x));
|
memcpy(ptr, &x, sizeof(x));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
@ -770,7 +765,7 @@ I_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
if (get_ulong(value, &val) < 0)
|
if (get_ulong(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&field, ptr, sizeof(field));
|
memcpy(&field, ptr, sizeof(field));
|
||||||
field = (unsigned int)SET(field, (unsigned int)val, size);
|
field = SET(unsigned int, field, (unsigned int)val, size);
|
||||||
field = SWAP_INT(field);
|
field = SWAP_INT(field);
|
||||||
memcpy(ptr, &field, sizeof(field));
|
memcpy(ptr, &field, sizeof(field));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
|
@ -804,7 +799,7 @@ l_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
if (get_long(value, &val) < 0)
|
if (get_long(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&x, ptr, sizeof(x));
|
memcpy(&x, ptr, sizeof(x));
|
||||||
x = SET(x, val, size);
|
x = SET(long, x, val, size);
|
||||||
memcpy(ptr, &x, sizeof(x));
|
memcpy(ptr, &x, sizeof(x));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
@ -818,7 +813,7 @@ l_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&field, ptr, sizeof(field));
|
memcpy(&field, ptr, sizeof(field));
|
||||||
field = SWAP_LONG(field);
|
field = SWAP_LONG(field);
|
||||||
field = (long)SET(field, val, size);
|
field = SET(long, field, val, size);
|
||||||
field = SWAP_LONG(field);
|
field = SWAP_LONG(field);
|
||||||
memcpy(ptr, &field, sizeof(field));
|
memcpy(ptr, &field, sizeof(field));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
|
@ -852,7 +847,7 @@ L_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
if (get_ulong(value, &val) < 0)
|
if (get_ulong(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&x, ptr, sizeof(x));
|
memcpy(&x, ptr, sizeof(x));
|
||||||
x = SET(x, val, size);
|
x = SET(unsigned long, x, val, size);
|
||||||
memcpy(ptr, &x, sizeof(x));
|
memcpy(ptr, &x, sizeof(x));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
@ -866,7 +861,7 @@ L_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&field, ptr, sizeof(field));
|
memcpy(&field, ptr, sizeof(field));
|
||||||
field = SWAP_LONG(field);
|
field = SWAP_LONG(field);
|
||||||
field = (unsigned long)SET(field, val, size);
|
field = SET(unsigned long, field, val, size);
|
||||||
field = SWAP_LONG(field);
|
field = SWAP_LONG(field);
|
||||||
memcpy(ptr, &field, sizeof(field));
|
memcpy(ptr, &field, sizeof(field));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
|
@ -901,7 +896,7 @@ q_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
if (get_longlong(value, &val) < 0)
|
if (get_longlong(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&x, ptr, sizeof(x));
|
memcpy(&x, ptr, sizeof(x));
|
||||||
x = SET(x, val, size);
|
x = SET(PY_LONG_LONG, x, val, size);
|
||||||
memcpy(ptr, &x, sizeof(x));
|
memcpy(ptr, &x, sizeof(x));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
@ -915,7 +910,7 @@ q_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&field, ptr, sizeof(field));
|
memcpy(&field, ptr, sizeof(field));
|
||||||
field = SWAP_8(field);
|
field = SWAP_8(field);
|
||||||
field = (PY_LONG_LONG)SET(field, val, size);
|
field = SET(PY_LONG_LONG, field, val, size);
|
||||||
field = SWAP_8(field);
|
field = SWAP_8(field);
|
||||||
memcpy(ptr, &field, sizeof(field));
|
memcpy(ptr, &field, sizeof(field));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
|
@ -948,7 +943,7 @@ Q_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
if (get_ulonglong(value, &val) < 0)
|
if (get_ulonglong(value, &val) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&x, ptr, sizeof(x));
|
memcpy(&x, ptr, sizeof(x));
|
||||||
x = SET(x, val, size);
|
x = SET(PY_LONG_LONG, x, val, size);
|
||||||
memcpy(ptr, &x, sizeof(x));
|
memcpy(ptr, &x, sizeof(x));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
}
|
}
|
||||||
|
@ -962,7 +957,7 @@ Q_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(&field, ptr, sizeof(field));
|
memcpy(&field, ptr, sizeof(field));
|
||||||
field = SWAP_8(field);
|
field = SWAP_8(field);
|
||||||
field = (unsigned PY_LONG_LONG)SET(field, val, size);
|
field = SET(unsigned PY_LONG_LONG, field, val, size);
|
||||||
field = SWAP_8(field);
|
field = SWAP_8(field);
|
||||||
memcpy(ptr, &field, sizeof(field));
|
memcpy(ptr, &field, sizeof(field));
|
||||||
_RET(value);
|
_RET(value);
|
||||||
|
|
Loading…
Reference in New Issue