[New-bugs-announce] [issue6069] casting error from ctypes array to structure

higstar report at bugs.python.org
Wed May 20 12:32:28 CEST 2009


New submission from higstar <adrian at higstar.com>:

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.

----------
assignee: theller
components: ctypes
messages: 88111
nosy: higstar, theller
severity: normal
status: open
title: casting error from ctypes array to structure
versions: Python 2.5, Python 2.6, Python 3.0

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue6069>
_______________________________________


More information about the New-bugs-announce mailing list