Issue 11920: ctypes: Strange bitfield structure sizing issue (original) (raw)

Consider the following: import ctypes

class struct1( ctypes.Structure ): pack = 1 fields = [ ( "first", ctypes.c_uint8, 1 ), ( "second", ctypes.c_uint8, 1 ), ( "third", ctypes.c_uint8, 1 ), ( "fourth", ctypes.c_uint8, 1 ), ( "fifth", ctypes.c_uint8, 1 ), ( "pad", ctypes.c_uint16, 11 ), ]

s1 = struct1() print ctypes.sizeof( s1 )

class struct2( ctypes.Structure ): pack = 1 fields = [ ( "first", ctypes.c_uint16, 1 ), ( "second", ctypes.c_uint16, 1 ), ( "third", ctypes.c_uint16, 1 ), ( "fourth", ctypes.c_uint16, 1 ), ( "fifth", ctypes.c_uint16, 1 ), ( "pad", ctypes.c_uint16, 11 ), ]

s2 = struct2() print ctypes.sizeof( s2 )

The output is: 3 2

I'm generating python code from real c code. The compiler I'm using for the real c code packs both of these structures into two bytes. I need a way to make the first example work in python like the compiler without having to modify the source code.

Is this possible?

So, knowing there's a potential cross platform inconsistency here, is there a proposed way to deal with this that doesn't involve modifying the real c code I'm interfacing with? That's not always an option.

On Mon, Apr 25, 2011 at 2:49 PM, Santoso Wijaya <report@bugs.python.org>wrote:

Santoso Wijaya <santoso.wijaya@gmail.com> added the comment:

What compilers were used to build your Python distro and the native structure?

I found out in _ctypes/cfield.c (lns. 76-95):

if (bitsize /* this is a bitfield request */ && pfield_size / we have a bitfield open / #ifdef MS_WIN32 / MSVC, GCC with -mms-bitfields */ && dict->size * 8 == pfield_size #else / GCC */ && dict->size * 8 <= *pfield_size #endif && (*pbitofs + bitsize) <= *pfield_size) { /* continue bit field */ fieldtype = CONT_BITFIELD; #ifndef MS_WIN32 } else if (bitsize /* this is a bitfield request */ && *pfield_size /* we have a bitfield open */ && dict->size * 8 >= *pfield_size && (pbitofs + bitsize) <= dict->size * 8) { / expand bit field */ fieldtype = EXPAND_BITFIELD; #endif

So the allocation of the extra byte for the structure seems to depend on Python's compiler. To make sure, I compiled a native structure using MSVC:

#pragma pack(1) typedef struct _struct1 { UINT8 first : 1; UINT8 second : 1; UINT8 third : 1; UINT8 fourth : 1; UINT8 fifth : 1; UINT16 pad : 11; } struct1;

And I got the same value (sizeof == 3).



Python tracker <report@bugs.python.org> <http://bugs.python.org/issue11920>