babaloveyou
babaloveyou

Reputation: 229

delphi2010 Traversal record of rtti

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.

the myrec.name is Chinese characters,the length of myrec.name is 64 byte , i can not read the myrec.name to memo, please help me!!!

Upvotes: 3

Views: 696

Answers (1)

David Heffernan
David Heffernan

Reputation: 612784

I'm on Delphi 2010, and I found a couple of issues with your code. First of all, I couldn't get the RTTI methods to work with the inline declaration of the character array. I changed it to:

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

If you declare the array inline, the way you had done, the call to GetValue raise an AV. That's probably fixed in XE, or quite possibly I'm using RTTI incorrectly.

Secondly, you need special treatment for 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;

Output:

1
Hello Stack Overflow

This obviously isn't production code, but it should at least get you back on the road!

P.S. This is the first time I've looked at the new RTTI functionality. It looks pretty nifty!

Upvotes: 2

Related Questions