Hallo zusammen,
hat jemand Erfahrung mit bitpacked record unter FPC ?
[...]
Ist das so korrekt? Ich hab ein kleines Test-programm geschrieben, dort funktioniert das Setzen und Lesen der Bits, aber funktioniert das in Kombination mit der
WinAPI/DirectDraw ? Hat da jemand Erfahrung
Ja, das ist so korrekt (
BitSizeOf(TDWRITE_LINE_BREAKPOINT)
gibt zum Beispiel korrekterweise
8 zurück). Du musst nur aufpassen, da wir keinerlei Garantie für irgendwelche Ausrichtungen in
bitpacked
Records oder Arrays geben, dass es für dich wirklich korrekt funktioniert (was aktuell zumindest unter i386 jedoch der Fall ist). Außerdem unterstützen solche Typen keine
RTTI (sollte in deinem Fall kein Problem sein, aber sicher ist sicher
).
Der
WinAPI bzw. DirectDraw ist es dann jedoch egal, ob das Record
bitpacked
ist oder nicht, da ja das Speicherlayout das gleiche ist. Solang die Daten sich alle innerhalb des einen Bytes befinden, solltest du da keine Probleme erhalten.
Ich hab auch mal nen kleinen Test gemacht als Vergleich zwischen dem Zugriff über
bitpacked
und über
inline
Getter/Setter:
Delphi-Quellcode:
program tbitpackedtest;
{$mode objfpc}
{$modeswitch advancedrecords}
{$IFDEF FPC}
type
Unsigned_Bit2 = 0 .. (1 shl 2) - 1;
{$ENDIF}
type
TDWRITE_LINE_BREAKPOINT = {$IFDEF FPC} bitpacked {$ENDIF} record
private
function GetIsWhitespaceProp: Boolean; inline;
procedure SetIsWhitespaceProp(aValue: Boolean); inline;
public
property IsWhitespaceProp: Boolean read GetIsWhitespaceProp write SetIsWhitespaceProp;
public
{$IFDEF FPC}
case Integer of
0:(
breakConditionBefore: Unsigned_Bit2;
breakConditionAfter: Unsigned_Bit2;
isWhitespace: boolean;
isSoftHyphen: boolean;
padding: Unsigned_Bit2);
1: (LineBreakpointConditions: UINT8);
{$ELSE}
LineBreakpointConditions: UINT8;
{$ENDIF}
end;
DWRITE_LINE_BREAKPOINT = TDWRITE_LINE_BREAKPOINT;
PDWRITE_LINE_BREAKPOINT = ^TDWRITE_LINE_BREAKPOINT;
function TDWRITE_LINE_BREAKPOINT.GetIsWhitespaceProp: boolean;
begin
Result := (LineBreakpointConditions and $10) <> 0;
end;
procedure TDWRITE_LINE_BREAKPOINT.SetIsWhitespaceProp(avalue: boolean);
begin
LineBreakPointConditions := (LineBreakpointConditions and not $10) or (Ord(avalue) shl 4);
end;
var
b: TDWRITE_LINE_BREAKPOINT;
begin
Writeln(bitsizeof(TDWRITE_LINE_BREAKPOINT), ' ', sizeof(TDWRITE_LINE_BREAKPOINT));
b.isWhitespace := True;
b.isWhitespaceProp := True;
end.
Der generierte Assemblercode ist dabei nahezu identisch:
Code:
# [49] b.isWhitespace := True;
movzbl U_P$TBITPACKEDTEST_B,%eax
orl $16,%eax
movb %al,U_P$TBITPACKEDTEST_B
# [50] b.isWhitespaceProp := True;
movzbl U_P$TBITPACKEDTEST_B,%eax
andl $-17,%eax
orl $16,%eax
movb %al,U_P$TBITPACKEDTEST_B
Wobei du aufpassen musst, da
inline
mit Record Methoden erst mit 2.7.1 korrekt funktioniert (davor musstest du die
Unit mit den
inline
Methoden immer frisch mitkompilieren, damit das geklappt hat; hab ich erst vor kurzem gefixt
).
Gruß,
Sven