Delphi2010 rtti traversal record

type
 myrec = record
 id:dWord;
 name:array[0..31] of  WideChar;
 three:dword;
 count:dword;
 ShuXing:Single;
 ShuXing2:dword;
 ShuXing3:dWORD;

  end;

var
  Form1: TForm1;
  mystr:TMemoryStream;
  nowmyrec:myrec;

implementation
 USES Rtti;
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);


var
  rttiContext: TRttiContext;
  rttiType: TRttiType;
  fields: TArray<TRttiField>;
  item: myrec;
  i:word;
begin
mystr:=TMemoryStream.Create;
mystr.LoadFromFile(ExtractFilePath(Application.exename)+'1.data');
mystr.Position:=20;
mystr.readbuffer(nowmyRec,88);




 rttiType := rttiContext.GetType(TypeInfo(myRec));
  fields := rttiType.GetFields;
   for i := low(fields) to high(fields) do
   begin
Memo1.Lines.Add(fields[i].GetValue(@nowmyRec).ToString );


   end;

end;

end.

myrec.name are hieroglyphs, myrec.name is 64 bytes long, I can not read myrec.name for a reminder, please help me.

+3
source share
1 answer

I am on Delphi 2010 and I found a couple of problems with your code. First of all, I could not get the RTTI methods to work with the built-in declaration of a character array. I changed it to:

type
  TCharArray = array[0..31] of WideChar;
  TRec = record
    id:dWord;
    name:TCharArray;
  end;

If you declare an inline array as you did, the call GetValuecalls AV. This is probably fixed in XE or maybe I'm using RTTI incorrectly.

Secondly, you need special handling of arrays as opposed to scalar values:

procedure Main;
var
  i, j: Integer;
  rec: TRec;
  rttiContext: TRttiContext;
  rttiType: TRttiType;
  fields: TArray<TRttiField>;
  val: TValue;
  s: string;
begin
  rec.id := 1;
  rec.name := 'Hello Stack Overflow';

  rttiType := rttiContext.GetType(TypeInfo(TRec));
  fields := rttiType.GetFields;
  for i := low(fields) to high(fields) do begin
    val := fields[i].GetValue(@rec);
    if val.IsArray then begin
      s := '';
      for j := 0 to val.GetArrayLength-1 do begin
        s := s+val.GetArrayElement(j).ToString;
      end;
      Writeln(s);
    end else begin
      Writeln(val.ToString);
    end;
  end;
end;

Conclusion:

1
Hello Stack Overflow

This is obviously not production code, but it should at least get you back on the road!

P.S. , RTTI. !

+2

Source: https://habr.com/ru/post/1796457/


All Articles