RTTI(四)相關函數2【轉自大富翁】

來源:互聯網
上載者:User

GetOrdProp 函數詳解

SetOrdProp 函數

GetEnumProp / SetEnumProp 函數

GetSetProp / SetSetProp 函數
GetObjectProp / SetObjectProp 函數

GetStrProp / SetStrProp 函數

⊙ GetOrdProp 函數詳解

GetOrdProp 是 Delphi RTTI 中使用頻繁的函數。GetOrdProp 根據物件控點和對象屬性的 TPropInfo 指標獲得對象的屬性值。它的傳回值是 Longint,需要強制轉換成相應的屬性類型才能使用。

function GetOrdProp(Instance: TObject; PropInfo: PPropInfo): Longint;

GetOrdProp 調用 TPropInfo.GetProc 函數指標得到屬性的傳回值。它的工作過程是:

如果該屬性的類型是 class 類型,那麼傳回值是 4 個位元組(物件控點)。

否則通過 TTypeData.OrdType 得到傳回值的類型,儲存在 BL 中。

{ TOrdType = (otSByte, otUByte, otSWord, otUWord, otSLong, otULong); }

檢查 TPropInfo.GetProc 的第一個位元組(注意是 GetProc 指標的第一個位元組):

如果 GetProc[0] = $FF,說明 GetProc 是 field offset;
如果 GetProc[0] = $FE,說明 GetProc 是 virtual method offset;
如果 GetProc[0] < $FE,說明 GetProc 是 static method;

然後根據不同的 GetProc 類型解析後,調用 GetProc。
根據 BL 中儲存的類型符號資訊修正傳回值(EAX)的符號資訊。
根據 BL 中儲存的類型的大小裁剪傳回值 EAX 為 EAX/AX/AL。
EAX(AX/AL) 即是返回的屬性值。

GetOrdProp 的彙編代碼及注釋如下:

function GetOrdProp(Instance: TObject; PropInfo: PPropInfo): Longint;asm  PUSH  EBX  PUSH  EDI  MOV  EDI,[EDX].TPropInfo.PropType  ; EDI <- PPTypeInfo  MOV  EDI,[EDI]  ; EDI <- PTypeInfo  MOV  BL,otSLong  ; BL  <- otSLong  CMP  [EDI].TTypeInfo.Kind,tkClass  ; if Prop is Class  JE  @@isClass  ; jmp @@isClass  XOR  ECX,ECX  ; ECX <- 0  MOV  CL,[EDI].TTypeInfo.Name.Byte[0]  ; CL  <- Name StrLength  MOV  BL,[EDI].TTypeInfo.Name[ECX+1].TTypeData.OrdType  ; BL  <- Prop OrdType  @@isClass:  MOV  ECX,[EDX].TPropInfo.GetProc  ; ECX <- GetProc Addr  CMP  [EDX].TPropInfo.GetProc.Byte[3],$FE ; cmp HiByte(GetProc), $FE  MOV  EDX,[EDX].TPropInfo.Index  ; EDX <- Prop Index  JB  @@isStaticMethod  ; if below $FE  JA  @@isField  ; if is $FF  {  the GetProc is a virtual method }  ; if is $FE  MOVSX  ECX,CX  { sign extend slot offs }  ADD  ECX,[EAX]  { vmt  + slotoffs  }  CALL  dword ptr [ECX]  { call vmt[slot]  }  JMP  @@final  @@isStaticMethod:  CALL  ECX  ; call GetProc directly  JMP  @@final  @@isField:  AND  ECX,$00FFFFFF  ; clear HiByte(GetProc)  ADD  ECX,EAX  ; ECX <- Field Addr  MOV  AL,[ECX]  ; AL  <- Field Addr[0]  CMP  BL,otSWord  ; if OrdType < otSWord  JB  @@final  ; Exit  MOV  AX,[ECX]  ; else AX <- Field[0..1]  CMP  BL,otSLong  ; if OrdType < otSLong  JB  @@final  ; Exit  MOV  EAX,[ECX]  ; else EAX <- Field[0..3]  @@final:  CMP  BL,otSLong  ; if OrdType >= otSLong  JAE  @@exit  ; Exit  CMP  BL,otSWord  ; if OrdType >= otSWord  JAE  @@word  ; jmp @@word  CMP  BL,otSByte  ; if OrdType = otSByte  MOVSX  EAX,AL  ; AL <- Sign(EAX)  JE  @@exit  ; Exit  AND  EAX,$FF  ; clear HiWord(EAX)  JMP  @@exit  ; Exit  @@word:  MOVSX  EAX,AX  ; AX <= Sign(EAX)  JE  @@exit  ; if OrdType = otSWord then Exit  AND  EAX,$FFFF  ; clear HiWord(EAX)  @@exit:  POP  EDI  POP  EBXend;

TypInfo.pas 中重載了 GetOrdProp 函數,將 PPropInfo 參數替換為 PropName,方便程式員調用,它其實也是調用了上面介紹的 GetOrdProp 函數。

function GetOrdProp(Instance: TObject; const PropName: string): Longint;begin  Result := GetOrdProp(Instance, FindPropInfo(Instance, PropName));end;

下面是使用 GetOrdProp 的例子:

Self.Width := Self.Width - GetOrdProp(Self, 'Height');

上面的語句相當於:

Self.Width := Self.Width - Self.Height;

* 後文介紹的 Get___Prop 系列函數或者調用本函數,或者它的實現方法與本函數類似。

SetOrdProp 函數

SetOrdProp 函數是 GetOrdProp 的逆過程,它調用 TPropInfo.SetProc 函數指標設定對象的屬性值。SetProc 指標的第一個位元組的意義同 GetProc 一樣,也是表示該 SetProc 是欄位位移、虛方法位移和靜態方法。

procedure SetOrdProp(Instance: TObject; PropInfo: PPropInfo; Value: Longint);

SetOrdProc 也根據屬性名稱重載了:

procedure SetOrdProp(Instance: TObject; const PropName: string; Value: Longint);

由於 SetOrdProp 的彙編代碼與 GetOrdProp 的幾乎一樣,在此就不再列出。作為練習,試用一下:

SetOrdProp(Self, 'Height', Self.Height + 10);

該語句的功能相當於:

Self.Height := Self.Height + 10;

* 後文介紹的 Set___Prop 系列函數或者調用本函數,或者它的實現方法與本函數類似。

GetEnumProp / SetEnumProp 函數

GetEnumProp 函數擷取枚舉類型屬性的枚舉字串,它調用 GetEnumName 轉換 GetOrdProp 的傳回值。

function GetEnumProp(Instance: TObject; PropInfo: PPropInfo): string;
function GetEnumProp(Instance: TObject; const PropName: string): string;

SetEnumProp 函數使用枚舉字串設定枚舉類型屬性值,它調用 GetEnumValue 轉換枚舉字串後再調用 SetOrdProp 設定屬性值。

procedure SetEnumProp(Instance: TObject; PropInfo: PPropInfo;
const Value: string);
procedure SetEnumProp(Instance: TObject; const PropName: string;
const Value: string);

GetSetProp / SetSetProp 函數

GetSetProp 函數用於擷取集合類型屬性的字串值,它也是調用 GetOrdProp 獲得屬性值,然後調用 SetToString 函數把數值轉換成字串。

注意:GetOrdProp 函數傳回值是 Integer,那麼它是如何表示可以儲存 256 個元素的集合類型呢?答案是:如果是 published 集合屬性,那麼該集合最大隻能是 4 個位元組,也就是最多隻能儲存 32 個元素。

function GetSetProp(Instance: TObject; PropInfo: PPropInfo;
Brackets: Boolean): string;
function GetSetProp(Instance: TObject; const PropName: string;
Brackets: Boolean = False): string;

SetSetProp 函數用於通過字串設定集合類型屬性的值。它先調用 StringToSet 函數把字串轉換為整數值,然後使用 SetOrdProp 函數設定屬性值。

procedure SetSetProp(Instance: TObject; PropInfo: PPropInfo;
const Value: string);
procedure SetSetProp(Instance: TObject; const PropName: string;
const Value: string);

實驗:  SetSetProp(Self, 'BorderIcons', '[biSystemMenu]');

GetObjectProp / SetObjectProp 函數

對象實際上是指標,也就是整數值,所以 GetObjectProp 直接調用 GetOrdProp 就可以了。

MinClass 參數指定得到的 Object 必須屬於某個 class ,如果不是則返回 nil 。

function GetObjectProp(Instance: TObject; PropInfo: PPropInfo;
MinClass: TClass = nil): TObject;
function GetObjectProp(Instance: TObject; const PropName: string;
MinClass: TClass = nil): TObject;

SetObjectProp 用於設定屬性的物件控點。ValidateClass 參數表示是否需要檢查傳入的物件類型與屬性資訊的類資訊是否相容。

procedure SetObjectProp(Instance: TObject; PropInfo: PPropInfo;
Value: TObject; ValidateClass: Boolean = True);
procedure SetObjectProp(Instance: TObject; const PropName: string;
Value: TObject);

例子:

var
MyFont: TFont;
begin
MyFont := TFont.Create;
MyFont.Height :=  20;
SetObjectProp(Self, 'Font', MyFont);
end;

GetStrProp / SetStrProp 函數

GetStrProp 函數用於獲得字串類型的屬性值。

function GetStrProp(Instance: TObject; PropInfo: PPropInfo): string;
function GetStrProp(Instance: TObject; const PropName: string): string;

由於 Delphi 支援三種類型的字串,GetStrProp 根據字串的類型,分別調用三個獲得字串屬性值的函數:

case PropInfo^.PropType^.Kind of
tkString: GetShortStrPropAsLongStr(Instance, PropInfo, Result);
tkLString: GetLongStrProp(Instance, PropInfo, Result);
tkWString: GetWideStrPropAsLongStr(Instance, PropInfo, Result);
end;

其中 GetShortStrPropAsLongStr 又調用了 GetShortStrProp;GetWideStrPropAsLongStr 又調用了 GetWideStrProp,進行字串間的類型轉換。

SetStrProp 函數用於設定字串類型的屬性值。它的實現方法與 GetStrProp 類似。

procedure SetStrProp(Instance: TObject; PropInfo: PPropInfo;
const Value: string);
procedure SetStrProp(Instance: TObject; const PropName: string;
const Value: string);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.