TRttiField.GetValue does not give the correct value

162 Views Asked by At

I'm on Delphi 10.3.

TTestRTTI = class
  field1: integer;
end;

procedure testRTTI();
var
  field : TRttiField;
  fields: TArray<TRttiField>;
  testInstance: TTestRTTI;
  val: Integer;
begin
  testInstance := TTestRTTI.Create();
  testInstance.field1 := 5;
  fields := TRttiContext.Create().GetType(TypeInfo(TTestRTTI)).GetFields();
  for field in fields do begin
    val := field.GetValue(@testInstance).AsInteger;
  end;
  // val is not 5 ?
  OutputDebugString(PChar(val.ToString()));
end;

It seems GetValue does not return the correct information. What am I doing wrong ?

Edit : It seems that Delphi returns a Long instead of an Integer ? Is this a platform problem ? I'm on Windows 10 64 bits.enter image description here

2

There are 2 best solutions below

2
muchos On

Okay so my problem with that I was passing the address of testInstance directly to GetValue(). Since testInstance is a class, that doesn't work.

Problem is, when working with generics, passing either one doesn't work. So instead of having a generic procedure like:

procedure TMyClass.DoStuff<T>(a: T);

You need :

procedure TMyClass.DoStuff<T>(a: Pointer);

And then you can pass a directly to PByte or GetValue.

0
Dalija Prasnikar On

The TRttiField.GetValue() function requires passing in a pointer to an instance to get the value of a field of that instance. However, your instance is an object and the reference to the object is already a pointer so you should pass it directly, instead of retrieving the address of the pointer itself.

Change the following line and remove the @ operator from the call:

val := field.GetValue(testInstance).AsInteger;

On the other hand, if your TTestRTTI would be a record instead of a class, then you would indeed need to use the @ operator when passing record instance to the GetValue function:

TTestRTTI = record
  field1: integer;
end;

var testInstance: TTestRTTI;

val := field.GetValue(@testInstance).AsInteger;