RTTI(四)相関関数2【転自大長者】

7888 ワード

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  EBX

end;

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は3種類の文字列をサポートしているため、GetStrPropは文字列のタイプに応じて、文字列の属性値を取得する3つの関数を呼び出します.
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);