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 vladris
Recipients higstar, terry.reedy, theller, vladris
Date 2011-06-25.05:02:04
SpamBayes Score 6.2644334e-13
Marked as misclassified No
Message-id <1308978125.42.0.864216889254.issue6069@psf.upfronthosting.co.za>
In-reply-to
Content
I took a look at this and I believe behavior is correct on Windows, the issue is with the test. For example this test is failing:

class closest_fit(ctypes.BigEndianStructure):
    _pack_      = 1    # aligned to 8 bits, not ctypes default of 32
    _fields_    = [
                   ("Data0",   ctypes.c_uint32, 32),
                   ("Data1",   ctypes.c_uint8, 3),
                   ("Data2",   ctypes.c_uint16, 12),
                  ]

But you also have this assumption when generating the test data:

size_of_structures_in_bytes = 6

I verified and this does not hold with MSVC compiler. Using VC++ 2005, this code

typedef struct Test {
	unsigned int x: 32; // uint_32 : 32
	unsigned char y: 3; // uint_8 : 3
	unsigned short int z: 12; // uint_16 : 12
} Test;

gives sizeof(Test) == 7. In Python, if you look at sizeof(closest_fit), it will also be 7.

Looking at cfield.c, seems this was taken into account when creating bit fields:

    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
    } else if (bitsize) {
        /* start new bitfield */
        fieldtype = NEW_BITFIELD;
        *pbitofs = 0;
        *pfield_size = dict->size * 8;
 
Though I don't know this first-hand, above code plus sizeof experiment leads me to believe that gcc packs bitfields differently than MSVC. Seems that gcc will expand existing bitfield trying to pack structure more tightly so indeed on Linux (or I assume Windows gcc build), size of this structure is 6 as gcc will combine these seeing that an unsigned short can hold all 15 bits required but with MSVC this won't work. MSVC will allocate both the c_uint8 and the c_uint16 once is sees that last 12 bits don't fit in remaining c_uint8.

As far as I can tell this is by design and Python matches expected MSVC structure packing for this test case.
History
Date User Action Args
2011-06-25 05:02:05vladrissetrecipients: + vladris, theller, terry.reedy, higstar
2011-06-25 05:02:05vladrissetmessageid: <1308978125.42.0.864216889254.issue6069@psf.upfronthosting.co.za>
2011-06-25 05:02:04vladrislinkissue6069 messages
2011-06-25 05:02:04vladriscreate