diff -r e2ab56295b56 Lib/ctypes/test/test_bitfields.py --- a/Lib/ctypes/test/test_bitfields.py Thu Jul 26 17:16:24 2012 +0300 +++ b/Lib/ctypes/test/test_bitfields.py Thu Jul 26 20:36:28 2012 +0200 @@ -188,6 +188,29 @@ self.assertEqual(X.c.offset, sizeof(c_short)*2) + def test_subclassed_bitfields(self): + class SubByte(c_ubyte): + def __repr__(self): + return "SubByte(%d)" % self.value + + class A(Structure): + _fields_ = [("lo", c_ubyte, 5), + ("hi", c_ubyte, 3)] + class B(Structure): + _fields_ = [("lo", SubByte, 5), + ("hi", SubByte, 3)] + class TestStruct(Union): + _fields_ = [("a", A), + ("b", B), + ("all", c_ubyte)] + + t = TestStruct() + for (hi, lo) in ((0, 0), (0, 0x1F), (0x03, 0x00), (0x03, 0x1F)): + t.a.lo, t.a.hi = lo, hi + self.assertEqual(t.all, lo + (hi << 5)) + self.assertEqual((t.a.hi, t.a.lo), (hi, lo)) + self.assertEqual((t.b.hi.value, t.b.lo.value), (hi, lo)) + def get_except(self, func, *args, **kw): try: func(*args, **kw) diff -r e2ab56295b56 Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c Thu Jul 26 17:16:24 2012 +0300 +++ b/Modules/_ctypes/_ctypes.c Thu Jul 26 20:36:28 2012 +0200 @@ -2644,7 +2644,8 @@ } PyObject * -PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr) +PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, + char *adr, Py_ssize_t size) { CDataObject *cmem; StgDictObject *dict; @@ -2663,7 +2664,13 @@ assert(CDataObject_Check(cmem)); cmem->b_length = dict->length; - cmem->b_size = dict->size; + if (size > 0) { + /* bitfields encode the bitsize in the lower byte, + and the bit offset in the upper byte + */ + cmem->b_size = size; + } else + cmem->b_size = dict->size; if (base) { /* use base's buffer */ assert(CDataObject_Check(base)); cmem->b_ptr = adr; @@ -2735,7 +2742,7 @@ dict = PyType_stgdict(type); if (dict && dict->getfunc && !_ctypes_simple_instance(type)) return dict->getfunc(adr, size); - return PyCData_FromBaseObj(type, src, index, adr); + return PyCData_FromBaseObj(type, src, index, adr, size); } /* @@ -4752,7 +4759,7 @@ assert(stgdict); /* Cannot be NULL fr pointer instances */ return PyCData_FromBaseObj(stgdict->proto, (PyObject *)self, 0, - *(void **)self->b_ptr); + *(void **)self->b_ptr, 0); } static int diff -r e2ab56295b56 Modules/_ctypes/callproc.c --- a/Modules/_ctypes/callproc.c Thu Jul 26 17:16:24 2012 +0300 +++ b/Modules/_ctypes/callproc.c Thu Jul 26 20:36:28 2012 +0200 @@ -901,7 +901,7 @@ Py_DECREF(retval); } } else - retval = PyCData_FromBaseObj(restype, NULL, 0, result); + retval = PyCData_FromBaseObj(restype, NULL, 0, result, 0); if (!checker || !retval) return retval; diff -r e2ab56295b56 Modules/_ctypes/ctypes.h --- a/Modules/_ctypes/ctypes.h Thu Jul 26 17:16:24 2012 +0300 +++ b/Modules/_ctypes/ctypes.h Thu Jul 26 20:36:28 2012 +0200 @@ -354,7 +354,7 @@ extern void _ctypes_add_traceback(char *, char *, int); -extern PyObject *PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr); +extern PyObject *PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr, Py_ssize_t size); extern char *_ctypes_alloc_format_string(const char *prefix, const char *suffix); extern int _ctypes_simple_instance(PyObject *obj);