C struct (with bitfields) to D and back

Jarrett Billingsley kb3ctd2 at yahoo.com
Sat Aug 5 16:09:44 PDT 2006


"Serg Kovrov" <kovrov at no.spam> wrote in message 
news:eb32p6$tai$1 at digitaldaemon.com...
> Hi all, I have a problem translating certain C structure to D. Here it is:
>
>> typedef struct tag_SCRIPT_CONTROL { DWORD uDefaultLanguage :16; DWORD 
>> fContextDigits :1; DWORD fInvertPreBoundDir :1; DWORD fInvertPostBoundDir 
>> :1; DWORD fLinkStringBefore :1; DWORD fLinkStringAfter :1; DWORD 
>> fNeutralOverride :1; DWORD fNumericOverride :1; DWORD fLegacyBidiClass 
>> :1; DWORD fReserved :8; } SCRIPT_CONTROL;
>
> It some sort of telling C compiler size of a struct member. I never used 
> such technique before. htod output following:
>
>> struct tag_SCRIPT_CONTROL
>> {
>>     DWORD __bitfield1;
>>     DWORD uDefaultLanguage() { return (__bitfield1 >> 0) & 0xffff; }
>>     DWORD uDefaultLanguage(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xffffffffffff0000) | (value << 0); return value; }
>>     DWORD fContextDigits() { return (__bitfield1 >> 16) & 0x1; }
>>     DWORD fContextDigits(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xfffffffffffeffff) | (value << 16); return value; }
>>     DWORD fInvertPreBoundDir() { return (__bitfield1 >> 17) & 0x1; }
>>     DWORD fInvertPreBoundDir(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xfffffffffffdffff) | (value << 17); return value; }
>>     DWORD fInvertPostBoundDir() { return (__bitfield1 >> 18) & 0x1; }
>>     DWORD fInvertPostBoundDir(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xfffffffffffbffff) | (value << 18); return value; }
>>     DWORD fLinkStringBefore() { return (__bitfield1 >> 19) & 0x1; }
>>     DWORD fLinkStringBefore(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xfffffffffff7ffff) | (value << 19); return value; }
>>     DWORD fLinkStringAfter() { return (__bitfield1 >> 20) & 0x1; }
>>     DWORD fLinkStringAfter(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xffffffffffefffff) | (value << 20); return value; }
>>     DWORD fNeutralOverride() { return (__bitfield1 >> 21) & 0x1; }
>>     DWORD fNeutralOverride(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xffffffffffdfffff) | (value << 21); return value; }
>>     DWORD fNumericOverride() { return (__bitfield1 >> 22) & 0x1; }
>>     DWORD fNumericOverride(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xffffffffffbfffff) | (value << 22); return value; }
>>     DWORD fLegacyBidiClass() { return (__bitfield1 >> 23) & 0x1; }
>>     DWORD fLegacyBidiClass(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xffffffffff7fffff) | (value << 23); return value; }
>>     DWORD fReserved() { return (__bitfield1 >> 24) & 0xff; }
>>     DWORD fReserved(DWORD value) { __bitfield1 = (__bitfield1 & 
>> 0xffffffff00ffffff) | (value << 24); return value; }
>> }
>> alias tag_SCRIPT_CONTROL SCRIPT_CONTROL;
>
> Which confusing me even more when input.
>
> It appears to be setter/getter properties providing some bit magic... I 
> must say my bit arithmetic sucks, but thats not the point. And the point 
> is, is it compatible with C API? This structure intended to be used with 
> extern (Windows) functions...

Wow, that's amazing; I didn't know htod would translate bitfields to 
properties like that.  It should be compatible with the C API, since that's 
what C bitfields do for you behind the scenes - shifting and masking.  And 
the positions look right.

About the only thing I can see that might not work as in C is assigning a 
value to a bitfield larger than it can hold - for instance, setting 
uDefaultLanguage to 0x10000 would set bit 17, one beyond the top bit of the 
field.  The solution of course would be to mask out the value to the size of 
the field. Might want Walter to see this. 





More information about the Digitalmars-d-learn mailing list