2015-01-06 64 views
4

這是我第一次在本網站上。通常,我在舊帖子中找到回覆沒有問題,但我沒有成功解決我的實際問題。FPC:記錄上的RTTI

我想知道如何使用RTTI函數在運行時知道Lazarus/FPC下記錄的屬性/成員?我知道如何爲一個類(Tpersistent後裔和已發佈的屬性)而不是FPC。有些鏈接指出如​​何在德爾福(從D2010開始)下做到這一點,但我不知道如何在拉撒路之下進行轉置。

在此先感謝您的幫助和幫助。 Salim Larhrib。

凱文:正如我之前所說,這是我的第一個要求。但是我明白。你是對的。這是我的代碼

procedure TMainForm.btRecordTHashListClick(Sender: TObject); 
var 
    pTData : PTypeData; 
    pTInfo : PTypeInfo; 
    TablePtr : PatableRecord; 
    Loop  : Integer; 
begin 
    // Set of Record pointers + HashList 

    // Create Container 
    if not Assigned(FTableRecList) then FTableRecList := TFPHashList.Create; 

    // Insert data 
    new(TablePtr); 
    TablePtr^.description := 'Dictionnaire des tables.'; 
    FTableRecList.add('atable', TablePtr); 

    new(TablePtr); 
    TablePtr^.description := 'Dictionnaire des fonctions.'; 
    FTableRecList.add('afunction', TablePtr); 

    new(TablePtr); 
    TablePtr^.description := 'Dictionnaire des listes d''option.'; 
    FTableRecList.add('alist', TablePtr); 

    // Read records 
    for Loop:=0 to FTableRecList.Count-1 do 
    begin 
    TablePtr := FTableRecList[Loop]; 
    ShowMessage('Parcours Index : ' + TablePtr^.description); 
    end; 

    // Find records 
    try 
    TablePtr := FTableRecList.Find('ddafunction'); 
    ShowMessage('Record finded : ' + TablePtr^.description); 
    except 
    ShowMessage('Not such record .'); 
    end; 
    try 
    TablePtr := FTableRecList.Find('afunction'); 
    ShowMessage('Record finded : ' + TablePtr^.description); 
    except 
    ShowMessage('No such record.'); 
    end; 

    // Free memory : To put later in TFPHashList wrapper 
    for Loop:=0 to FTableRecList.Count-1 do Dispose(PatableRecord(FTableRecList[Loop])); 

// RTTI 
    pTInfo := TypeInfo(TatableRecord); 

    pTData := GetTypeData(pTInfo); 
    ShowMessage('Member count = '+IntToStr(pTData^.PropCount)); 
end; 
+0

SO將有助於問題,所以不會寫代碼或指導您的地方找到的代碼。這是你的工作。 – KevinDTimm

+0

你說得對。我同意你的評論。請在編輯的問題上方找到添加的代碼。 –

+1

一旦打開相應的[編譯器模式](http://www.freepascal.org/docs-html/user/userse33.html),Free Pascal應該具有相當不錯的Delphi兼容性。所以下面的答案可能是有用的http://stackoverflow.com/a/23824290/2626313(我用Google:'site:stackoverflow.com delphi rtti record'找到它) – xmojmr

回答

5

警告:它的工作原理與FPC 2.7.1或更高版本。

您可以使用指針處理記錄字段。下面是例子:

program rttitest; 

uses 
    TypInfo; 

type 
    TMyRec = record 
     p1: Integer; 
     p2: string; 
    end; 

var 
    td: PTypeData; 
    ti: PTypeInfo; 
    mf: PManagedField; 
    p: Pointer; 
    f: Pointer; 

    r: TMyRec; 

begin 
    r.p1 := 312; 
    r.p2 := 'foo-bar'; 

    ti := TypeInfo(r); 
    td := GetTypeData(ti); 

    Writeln(td^.ManagedFldCount); // Get count of record fields 

    // After ManagedFldCount TTypeData contains list of the TManagedField records 
    // So ... 
    p := @(td^.ManagedFldCount); // Point to the ManagedFldCount ... 
    // Inc(p, SizeOf(Integer)); // Skip it (Wrong for 64-bit targets) 
    // Next line works for both 
    Inc(p, SizeOf(td^.ManagedFldCount)); // Skip it 

    mf := p; // And now in the mf we have data about first record's field 
    Writeln(mf^.TypeRef^.Name); 

    Write(r.p1); // Current value 
    f := @r; 
    Inc(f, mf^.FldOffset); // Point to the first field 
    Integer(f^) := 645; // Set field value 
    Writeln(r.p1); // New value 

    // Repeat for the second field 
    Inc(p, SizeOf(TManagedField)); 
    mf := p; 
    Writeln(mf^.TypeRef^.Name); 

    Write(r.p2); 
    f := @r; 
    Inc(f, mf^.FldOffset); 
    string(f^) := 'abrakadabra'; 
    Writeln(r.p2); 


    Readln; 
end. 
+1

https://ideone.com/支持語言' Pascal(fpc)(fpc 2.6.2)''但你的代碼片段不會在那裏編譯,因爲它是由於'錯誤:標識符未找到'PManagedField「'。你能創建一個可執行的證明你的代碼正在工作嗎? – xmojmr

+2

@xmojmr是的。抱歉。這只是因爲我現在正在使用FPC的最新svn trunk(3.1.1)。而最新的穩定FPC(2.6.4)還不包含此功能。 – Abelisto

+0

我使用fpc 2.6.4。我會更新它並恢復。無論如何,謝謝你的幫助。 –