I would like to declare a record in Delphi that contains the same layout as it has in C.
For those interested : This record is part of a union in the Windows OS's LDT_ENTRY record. (I need to use this record in Delphi because I'm working on an Xbox emulator in Delphi - see project Dxbx on sourceforge).
Anyway, the record in question is defined as:
struct
{
DWORD BaseMid : 8;
DWORD Type : 5;
DWORD Dpl : 2;
DWORD Pres : 1;
DWORD LimitHi : 4;
DWORD Sys : 1;
DWORD Reserved_0 : 1;
DWORD Default_Big : 1;
DWORD Granularity : 1;
DWORD BaseHi : 8;
}
Bits;
As far as I know, there are no bit-fields possible in Delphi. I did try this:
Bits = record
BaseMid: Byte; // 8 bits
_Type: 0..31; // 5 bits
Dpl: 0..3; // 2 bits
Pres: Boolean; // 1 bit
LimitHi: 0..15; // 4 bits
Sys: Boolean; // 1 bit
Reserved_0: Boolean; // 1 bit
Default_Big: Boolean; // 1 bit
Granularity: Boolean; // 1 bit
BaseHi: Byte; // 8 bits
end;
But alas: it's size becomes 10 bytes, instead of the expected 4. I would like to know how I should declare the record, so that I get a record with the same layout, the same size, and the same members. Preferrably without loads of getter/setters.
TIA.
Thanks everyone!
Based on this information, I reduced this to :
The index is encoded as follows :
(BitOffset shl 8) + NrBits
. Where 1<=NrBits<=32 and 0<=BitOffset<=31Now, I can get and set these bits as follows :
Pretty nifty, don't you think?!?!
PS: Rudy Velthuis now included a revised version of this in his excellent "Pitfalls of converting"-article.
Ok, my bit manipulation is a bit rusty, so I could have reversed the bytes. But the code below gives the general idea:
Rudy's Delphi Corner is the best resource I know of regarding Delphi and C/C++ interoperability. His Pitfalls of conversion is pretty much a must read when using C/C++ APIs in Delphi. The chapter you'll be most interested in is Records and alignment -> Bitfields, but I urge you to read the entire thing top to bottom, twice. The other articles are definitely worth the time investment, too.
Well, you basically need to get down to the dirty with bit-manipulation.
Why, specifically, do you need to retain that structure?
If you only need to talk to a legacy program that either talks in this dialect (TCP/IP or similar), or stores data in this manner (files, etc.), then I would map a normal Delphi structure to a bit-version compatible. In other words, I would use a normally structured Delphi structure in memory, and write code to write and read that structure in a compatible manner.
If you need to save memory, I would make getters and setters that manipulate bits of internal integers or similar. This will have a performance impact, but not much more than what the original C program would have, the only difference is that the bit-manipulation would be added by compiler magic in the C version, whereas you will have to write it yourself.
If you don't have many records in memory, and don't need to talk to another program, I'd use a natural Delphi structure. Trade-off for higher performance will be more memory used.
But it all depends on your criteria.
In any case, you won't be able to talk the Delphi compiler into doing the same job for you as the C compiler.
PACKED RECORD, suggested by another here, doesn't do that, and was never meant to. It will only remove alignment padding to put integers on 32-bit boundaries and similar, but won't pack multiple fields into one byte.
Note that a common way to do this is through Delphi SETS, which are implementing internally using bit-fields. Again, you will have different code than the C variant.