digitalmars.D.learn - Converting C/C++ bit fields...
- "Regan Heath" <regan netwin.co.nz> Aug 09 2005
- Vathix <chris dprogramming.com> Aug 09 2005
- "Regan Heath" <regan netwin.co.nz> Aug 09 2005
- "Ben Hinkle" <bhinkle mathworks.com> Aug 09 2005
- Burton Radons <burton-radons smocky.com> Aug 09 2005
- Burton Radons <burton-radons smocky.com> Aug 09 2005
- "Regan Heath" <regan netwin.co.nz> Aug 09 2005
- "Ben Hinkle" <ben.hinkle gmail.com> Aug 09 2005
- "Regan Heath" <regan netwin.co.nz> Aug 09 2005
I'd like to find out what techniques people have been using to convert
C/C++ structs containing bitfields to D, take for example this struct:
typedef struct _DCB {
DWORD DCBlength; /* sizeof(DCB) */
DWORD BaudRate; /* Baudrate at which running */
DWORD fBinary: 1; /* Binary Mode (skip EOF check) */
DWORD fParity: 1; /* Enable parity checking */
DWORD fOutxCtsFlow:1; /* CTS handshaking on output */
DWORD fOutxDsrFlow:1; /* DSR handshaking on output */
DWORD fDtrControl:2; /* DTR Flow control */
DWORD fDsrSensitivity:1; /* DSR Sensitivity */
DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
DWORD fOutX: 1; /* Enable output X-ON/X-OFF */
DWORD fInX: 1; /* Enable input X-ON/X-OFF */
DWORD fErrorChar: 1; /* Enable Err Replacement */
DWORD fNull: 1; /* Enable Null stripping */
DWORD fRtsControl:2; /* Rts Flow control */
DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
DWORD fDummy2:17; /* Reserved */
WORD wReserved; /* Not currently used */
WORD XonLim; /* Transmit X-ON threshold */
WORD XoffLim; /* Transmit X-OFF threshold */
BYTE ByteSize; /* Number of bits/byte, 4-8 */
BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */
BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */
char XonChar; /* Tx and Rx X-ON character */
char XoffChar; /* Tx and Rx X-OFF character */
char ErrorChar; /* Error replacement char */
char EofChar; /* End of Input character */
char EvtChar; /* Received Event character */
WORD wReserved1; /* Fill for now. */
} DCB, *LPDCB;
My initial thought was to use bit, bit[2] and bit[17] but of course D
allocates 1 byte for each stand alone 'bit' so the structure ends up
totally the wrong size.
Next I tried a bit[32] called _bits (this should make the struct size
correct), and some aliases, eg.
alias _bits[0] fBinary;
but I get the error "_bits is used as a type". That is a little odd
considering I can write "alias EvtChar bob" (is this using EvtChar as a
type?)
Lastly I tried to use properties, i.e.
bit fBinary() { return _bits[0]; }
bit fBinary(bit b) { _bits[0] = b; return fBinary; }
these seem to work for the single bit ones, but the 2 bit ones:
bit[2] fDtrControl() { return _bits[4..6]; }
bit[2] fDtrControl(bit[2] b) { _bits[4..6] = b[]; return fDtrControl; }
that's no good, you cannot return a 'static' bit[2].
I then tried:
ubyte toUbyte(bit[] ba) { ubyte v = 0; foreach(bit b; ba) { v *= 2; v
+= b; } return v; }
ubyte fDtrControl() { return toUbyte(_bits[4..6]); }
ubyte fDtrControl(ubyte b) { _bits[4..6] = (cast(bit*)&b)[0..2]; return
fDtrControl; }
but that gives an array bounds error in the setter. I didn't investigate
this any further, the effort required already is quite ridiculous, such
that I figure there must or should be a better solution.
Thoughts?
Regan
Aug 09 2005
On Tue, 09 Aug 2005 07:54:16 -0400, Regan Heath <regan netwin.co.nz> wrote:I'd like to find out what techniques people have been using to convert C/C++ structs containing bitfields to D
How about masking and shifting DWORD bits
Aug 09 2005
On Tue, 09 Aug 2005 08:12:17 -0400, Vathix <chris dprogramming.com> wrote:On Tue, 09 Aug 2005 07:54:16 -0400, Regan Heath <regan netwin.co.nz> wrote:I'd like to find out what techniques people have been using to convert C/C++ structs containing bitfields to D
How about masking and shifting DWORD bits
Sure, but I want to be able to say: DCB a; a.fParity = true; ..etc.. which I guess I can do, if I define a getter/setter for each one, and do all the bit shifting etc in them. All that effort/work.. seems like it _should_ be easier. Regan
Aug 09 2005
"Regan Heath" <regan netwin.co.nz> wrote in message news:opsu8ooqhn23k2f5 nrage.netwin.co.nz...I'd like to find out what techniques people have been using to convert C/C++ structs containing bitfields to D, take for example this struct:
Thoughts?
import std.intrinsic; // a bit field template BitField(uint n, alias data) { int get(){ return bt(&data,n); } void set(int m){m?bts(&data,n):btr(&data,n);} } // a two-bit field template BitField2(uint n, alias data) { int get(){ return data >> n & 3; } void set(int m){ data = (data & ~(3<<n)) | (m<<n) ;} } struct Foo { uint fields; mixin BitField!(0,fields) f1; mixin BitField!(1,fields) f2; mixin BitField2!(2,fields) f3; mixin BitField!(4,fields) f4; } int main() { Foo x; x.f1.set = true; x.f3.set = 3; x.f4.set = true; printf("fields: %d\n",x.fields); printf("x.f1 %d\n", x.f1.get); printf("x.f2 %d\n", x.f2.get); printf("x.f3 %d\n", x.f3.get); printf("x.f4 %d\n", x.f4.get); return 0; }
Aug 09 2005
Ben Hinkle wrote:"Regan Heath" <regan netwin.co.nz> wrote in message news:opsu8ooqhn23k2f5 nrage.netwin.co.nz...I'd like to find out what techniques people have been using to convert C/C++ structs containing bitfields to D, take for example this struct:
[snip]Thoughts?
import std.intrinsic; // a bit field template BitField(uint n, alias data) { int get(){ return bt(&data,n); } void set(int m){m?bts(&data,n):btr(&data,n);} } // a two-bit field template BitField2(uint n, alias data) { int get(){ return data >> n & 3; } void set(int m){ data = (data & ~(3<<n)) | (m<<n) ;} } struct Foo { uint fields; mixin BitField!(0,fields) f1; mixin BitField!(1,fields) f2; mixin BitField2!(2,fields) f3; mixin BitField!(4,fields) f4; } int main() { Foo x; x.f1.set = true; x.f3.set = 3; x.f4.set = true; printf("fields: %d\n",x.fields); printf("x.f1 %d\n", x.f1.get); printf("x.f2 %d\n", x.f2.get); printf("x.f3 %d\n", x.f3.get); printf("x.f4 %d\n", x.f4.get); return 0; }
Clever boy. I'll need to remember that. I'd use the more general: template BitField (uint start, uint count, alias data, type = uint) { static assert ((1L << (start + count)) - 1 <= data.max); const uint mask = (1 << count) - 1; type get () { return cast (type) ((data >> start) & mask); } type set (type value) { data = (data & ~(mask << start)) | ((cast (typeof (data)) value & mask) << start); return value; } } Too bad opCall doesn't work with mixins.
Aug 09 2005
Burton Radons wrote:const uint mask = (1 << count) - 1;
That should be "const typeof (data) mask = (1UL << count) - 1;" so that it works with long.
Aug 09 2005
Nice! Thanks. Still, it would be nice if D had a better way to handle bitfields, if only to ease conversion of C/C++ structs containing them. The fact that we're not using the built in bit support suggests to me that it's not as useful as it should be. Regan On Tue, 9 Aug 2005 10:25:44 -0400, Ben Hinkle <bhinkle mathworks.com> wrote:"Regan Heath" <regan netwin.co.nz> wrote in message news:opsu8ooqhn23k2f5 nrage.netwin.co.nz...I'd like to find out what techniques people have been using to convert C/C++ structs containing bitfields to D, take for example this struct:
Thoughts?
import std.intrinsic; // a bit field template BitField(uint n, alias data) { int get(){ return bt(&data,n); } void set(int m){m?bts(&data,n):btr(&data,n);} } // a two-bit field template BitField2(uint n, alias data) { int get(){ return data >> n & 3; } void set(int m){ data = (data & ~(3<<n)) | (m<<n) ;} } struct Foo { uint fields; mixin BitField!(0,fields) f1; mixin BitField!(1,fields) f2; mixin BitField2!(2,fields) f3; mixin BitField!(4,fields) f4; } int main() { Foo x; x.f1.set = true; x.f3.set = 3; x.f4.set = true; printf("fields: %d\n",x.fields); printf("x.f1 %d\n", x.f1.get); printf("x.f2 %d\n", x.f2.get); printf("x.f3 %d\n", x.f3.get); printf("x.f4 %d\n", x.f4.get); return 0; }
Aug 09 2005
Still, it would be nice if D had a better way to handle bitfields, if only to ease conversion of C/C++ structs containing them. The fact that we're not using the built in bit support suggests to me that it's not as useful as it should be.
I haven't read the docs in detail but probably bit arrays have too much freedom in how they are implemented to be reliable for replacing C bit fields. ie- the packing and alignment become crucial and that's something that the shifting implementation can control (since they have to control it). To me the only problem with bitfields is that the auto .h->.d translator (I can't remember the name of the program) seems to ignore them so any struct with a bitfield gets hosed (without warning, I believe).
Aug 09 2005
On Tue, 9 Aug 2005 19:07:53 -0400, Ben Hinkle <ben.hinkle gmail.com> wrote:Still, it would be nice if D had a better way to handle bitfields, if only to ease conversion of C/C++ structs containing them. The fact that we're not using the built in bit support suggests to me that it's not as useful as it should be.
I haven't read the docs in detail but probably bit arrays have too much freedom in how they are implemented to be reliable for replacing C bit fields. ie- the packing and alignment become crucial and that's something that the shifting implementation can control (since they have to control it). To me the only problem with bitfields is that the auto .h->.d translator (I can't remember the name of the program) seems to ignore them so any struct with a bitfield gets hosed (without warning, I believe).
I think the problem with .h->.d translations is that there is no simple, easy way to translate bitfields. Why can't I use: bit[32] data; alias data[0] a; alias data[1] b; alias data[2] c; ..etc..? Regan
Aug 09 2005









"Regan Heath" <regan netwin.co.nz> 