This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author higstar
Recipients higstar, theller
Date 2009-05-20.10:32:24
SpamBayes Score 3.867129e-12
Marked as misclassified No
Message-id <1242815548.73.0.540935568828.issue6069@psf.upfronthosting.co.za>
In-reply-to
Content
Structure fails to correctly cast from a 2 byte bitfield.

From my very limited investigation, is looks like when using a member
type of less than the total size of the structure (or at least the size
of any byte boundaries) the casting is not done correctly?

I created this test.py and appended the results below:

---
import ctypes
import time

class closest_fit(ctypes.BigEndianStructure):
#    _pack_      = 1    # aligned to 8 bits, not ctypes default of 32
    _fields_    = [
                   ("Data0",   ctypes.c_ubyte, 7),
                   ("Data1",   ctypes.c_ubyte, 8),
                   ]

class all_ulong(ctypes.BigEndianStructure):
#    _pack_      = 1    # aligned to 8 bits, not ctypes default of 32
    _fields_    = [
                   ("Data0",   ctypes.c_ulonglong, 7),
                   ("Data1",   ctypes.c_ulonglong, 8),
                  ]

def castbytes(type):
    buffer = (ctypes.c_byte * 2)()
    buffer[0] = 0x55
    buffer[1] = 0x55
    return ctypes.cast(ctypes.pointer(buffer),
ctypes.POINTER(type)).contents

def print_members(test):
    print("Data0 is 0x%X, Data1 is 0x%X for %s"%(test.Data0, test.Data1,
test.__class__.__name__))

test_classes = [ closest_fit, all_ulonglong]

Failed = False
tests = [castbytes(type) for type in test_classes]
for test in tests:
    print_members(test)
    if not tests[0].Data0 == tests[1].Data0: 
        Failed = True
    if not tests[0].Data1 == tests[1].Data1: 
        Failed = True

if Failed:
    print("Failed")
else:
    print("Passed")
---

>c:\python25\python.exe test.py
Data0 is 0x2A, Data1 is 0x55 for closest_fit
Data0 is 0x2A, Data1 is 0xAA for all_ulonglong
Failed

>c:\python26\python.exe test.py
Data0 is 0x2A, Data1 is 0x55 for closest_fit
Data0 is 0x2A, Data1 is 0xAA for all_ulonglong
Failed

>c:\python30\python.exe test.py
Data0 is 0x2A, Data1 is 0x55 for closest_fit
Data0 is 0x2A, Data1 is 0xAA for all_ulonglong
Failed

As you can see the second member Data1, should be 0xAA, however when
using c_ubyte types for members the value is not offset by one bit.

As you can see using c_ulonglong for all members avoids this issue,
however this results in a read only structure (see Issue 6068).

I am using structures to cast CAN messages which are 8 bytes, with very
funky bit fields crossing all sorts of byte boundaries, so I essentially
expected that ctypes would provide a method for an arbitrary bit field
definition for use within python.  Hopefully this is just my bad ctypes
driving, or a simple fix.
History
Date User Action Args
2009-05-20 10:32:29higstarsetrecipients: + higstar, theller
2009-05-20 10:32:28higstarsetmessageid: <1242815548.73.0.540935568828.issue6069@psf.upfronthosting.co.za>
2009-05-20 10:32:26higstarlinkissue6069 messages
2009-05-20 10:32:24higstarcreate