Skip to content

Commit

Permalink
gh-73939: Fix bitfiled not matching C on mac/linux.
Browse files Browse the repository at this point in the history
  • Loading branch information
thesamprice authored and Sam Price committed Mar 27, 2023
1 parent 2cdc518 commit 2b82490
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
24 changes: 24 additions & 0 deletions Lib/test/test_ctypes/test_structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,30 @@ class Test8(Union):
self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes '
'a union by value, which is unsupported.')

def test_bitfield_matches_c(self):
class Test9(Structure):
_pack_ = 1
_fields_ = (('A', c_uint16), # 2 bytes
('B', c_uint16, 9),
('C', c_uint16, 1),
('D', c_uint16, 1),
('E', c_uint16, 1),
('F', c_uint16, 1),
('G', c_uint16, 3), # 4 bytes
('H', c_uint32, 10),
('I', c_uint32, 20),
('J', c_uint32, 2)) # 8 bytes
dll = CDLL(_ctypes_test.__file__)
func = dll._testfunc_bitfield_by_reference3
func.restype = c_long
func.argtypes = (POINTER(Test9),c_long,)
ind = 0
for field in Test9._fields_:
test9 = Test9()
setattr(test9,field[0], 1)
self.assertEqual(func(test9, ind), 1)
ind += 1

class PointerMemberTestCase(unittest.TestCase):

def test(self):
Expand Down
25 changes: 25 additions & 0 deletions Modules/_ctypes/_ctypes_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,31 @@ _testfunc_bitfield_by_reference2(Test7 *in) {
return result;
}

typedef struct{
uint16_t A ;
uint16_t B : 9;
uint16_t C : 1;
uint16_t D : 1;
uint16_t E : 1;
uint16_t F : 1;
uint16_t G : 3;
uint32_t H : 10;
uint32_t I : 20;
uint32_t J : 2;
} Test9;

EXPORT(long)
_testfunc_bitfield_by_reference3(Test9 *in, long pos) {
long data[] = {in->A , in->B , in->C , in->D , in->E , in->F , in->G , in->H , in->I , in->J};
long data_length = (long) (sizeof(data)/sizeof(data[0]));
if(pos < 0)
return -1;
if(pos >= data_length)
return -1;

return data[pos];
}

typedef union {
signed int A: 1, B:2, C:3, D:2;
} Test8;
Expand Down
1 change: 1 addition & 0 deletions Modules/_ctypes/cfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index,
#ifndef MS_WIN32
} else if (bitsize /* this is a bitfield request */
&& *pfield_size /* we have a bitfield open */
&& *pfield_size != *pbitofs /* Current field has been filled, start new one */
&& dict->size * 8 >= *pfield_size
&& (*pbitofs + bitsize) <= dict->size * 8) {
/* expand bit field */
Expand Down

0 comments on commit 2b82490

Please sign in to comment.