I need to copy a packed record
to TByteDynArray
in Delphi.
PMyRec = ^TMyRec;
TMyRec = packed record
Header: THeaderRec;
Timestamp: TTimeStamp; // time of event
PLoc: TLocationRec;
A: word;
end;
Below is the code snippet that I have for doing that.
xxx: TByteDynArray;
m_arr : TMyRec;
SetLength(xxx,sizeof(TMyRec));
offset := offset + sizeof(THeaderRec);
System.Move(xxx[offset], m_arr.Timestamp ,sizeof(TTimeStamp));
offset := offset + sizeof(TTimeStamp);
System.Move(xxx[offset], m_arr.PLoc,sizeof(TLocationRec));
This somehow doesn't seem to do the copying properly. Can someone point out if I am doing something wrong?
If you are wanting to copy FROM the record TO the byte array, then your code is doing the opposite. Pay attention to the parameters of System.Move()
. Its first parameter is the Source, its second parameter is the Destination. This is different than other APIs, like memcpy()
, CopyMemory()
, etc.
Try this:
offset := 0;
System.Move(m_arr.Header, xxx[offset], sizeof(THeaderRec));
Inc(offset, sizeof(THeaderRec));
System.Move(m_arr.Timestamp, xxx[offset], sizeof(TTimeStamp));
Inc(offset, sizeof(TTimeStamp));
System.Move(m_arr.PLoc, xxx[offset], sizeof(TLocationRec));
Inc(offset, sizeof(TLocationRec));
System.Move(m_arr.A, xxx[offset], sizeof(Word));
Or, you can copy the entire record in one go:
System.Move(m_arr, xxx[0], sizeof(TMyRec));
With that said, if you need to do per-field copies, I would suggest letting the compiler calculate the field offsets for you, eg:
offset := Integer(@PMyRec(nil).Header);
System.Move(m_arr.Header, xxx[offset], sizeof(THeaderRec));
offset := Integer(@PMyRec(nil).Timestamp);
System.Move(m_arr.Timestamp, xxx[offset], sizeof(TTimeStamp));
offset := Integer(@PMyRec(nil).PLoc);
System.Move(m_arr.PLoc, xxx[offset], sizeof(TLocationRec));
offset := Integer(@PMyRec(nil).A);
System.Move(m_arr.A, xxx[offset], sizeof(Word));
Or better, simply do not use Move()
at all. You can instead type-cast the allocated byte array and use standard field assignments, eg:
PMyRec(xxx)^.Header := m_arr.Header;
PMyRec(xxx)^.Timestamp := m_arr.Timestamp;
PMyRec(xxx)^.PLoc := m_arr.PLoc;
PMyRec(xxx)^.A := m_arr.A;
Or, to copy the entire record:
PMyRec(xxx)^ := m_arr;