在运行时获取delphi记录中字段的偏移量

Blo*_*ard 6 delphi struct pointers rtti delphi-7

给定记录类型:

TItem = record
   UPC : string[20];
   Price : Currency;
   Cost : Currency;
   ...
end; 
Run Code Online (Sandbox Code Playgroud)

并且字段的名称为字符串,如何在记录中获取该字段的偏移量?我需要在运行时执行此操作 - 要在运行时决定要访问的字段的名称.

例:

var
   pc : Integer;
   fieldName : string;
   value : Currency;
begin
   pc := Integer(@item);                    // item is defined and filled elsewhere
   fieldName := Text1.Text;                 // user might type 'Cost' or 'Price' etc
   Inc(pc, GetItemFieldOffset(fieldName));  // how do I implement GetItemFieldOffset?
   value := PCurrency(pc)^;
   ..
Run Code Online (Sandbox Code Playgroud)

我正在使用Delphi 7.

ale*_*lex 8

你不能.Delphi 7不会为记录发出RTTI.还有其他选项(如前面的答案所示),但这些选项需要手动映射"Field Name" - >"Offset".


Dan*_*ett 5

正如 alex 所说,Delphi 7 不会发出记录的 RTTI,因此您无法在运行时检索所需的信息。但是,在更高版本(Delphi 2010+)中确实如此,并且代码如下:

TItem = record
   UPC : string[20];
   Price : Currency;
   Cost : Currency;
//...
end;
    var
       rttiContext: TRttiContext;
       rttiType: TRttiType;
       fields: TArray<TRttiField>;
       item: TItem;
    begin
        rttiType := rttiContext.GetType(TypeInfo(TItem));
        caption := rttiType.Name + ' {';
        fields := rttiType.GetFields;
        for i := low(fields) to high(fields) do
        begin
          caption := caption +'{name='+fields[i].Name+',';
          caption := caption +'offset='+IntToStr(fields[i].Offset)+'}';
        end;
        caption := caption + '}';
Run Code Online (Sandbox Code Playgroud)

将生成 'TItem {{name=UPC,offset=0}{name=Price,offset=24}{name=Cost,offset=32}}'

您还可以使用以下方法在特定实例中设置字段值(尽管您实际上还应该验证类型):

if fields[i].Name = 'Price' then
  fields[i].SetValue(@item, 10);
Run Code Online (Sandbox Code Playgroud)