Re: [delphi-br] Re: MethodAddress retornando NIL [CANCELADO]
propriedades da seção published e métodos da public métodos private e protected não podem ser chamados externos à classe, pois isso quebra o paradigma da orientação a objetos o/ Em 19/07/2010 22:07, Fabricio Colombo escreveu: Essa rotina só funciona em um método declarado na seção published, correto?
Re: [delphi-br] Re: MethodAddress retornando NIL [CANCELADO]
Corrigindo... na empresa a gente usa o 2007 tb... e tem a mesma rotina funcionando não sei quanto as anteriores, pois não lembro de ter utilizado mto a rtti o/ Em 21/07/2010 13:10, Roni Rodrigo escreveu: eu to usando a 2010... mas se eu não me engano eu vi isso na 2009 tb... o/ Em 21/07/2010 12:59, Rubem Rocha escreveu: Então a RTTI foi revisada para atuar no escopo public de objetos. Isso aconteceu a partir de qual versão do Delphi? Sds. De: delphi-br@yahoogrupos.com.br mailto:delphi-br%40yahoogrupos.com.br mailto:delphi-br%40yahoogrupos.com.br [mailto:delphi-br@yahoogrupos.com.br mailto:delphi-br%40yahoogrupos.com.br mailto:delphi-br%40yahoogrupos.com.br] Em nome de Roni Rodrigo Enviada em: quarta-feira, 21 de julho de 2010 11:51 Para: delphi-br@yahoogrupos.com.br mailto:delphi-br%40yahoogrupos.com.br mailto:delphi-br%40yahoogrupos.com.br Assunto: Re: [delphi-br] Re: MethodAddress retornando NIL [CANCELADO] propriedades da seção published e métodos da public métodos private e protected não podem ser chamados externos à classe, pois isso quebra o paradigma da orientação a objetos o/ Em 19/07/2010 22:07, Fabricio Colombo escreveu: Essa rotina só funciona em um método declarado na seção published, correto? [As partes desta mensagem que não continham texto foram removidas]
Re: [delphi-br] Re: MethodAddress retornando NIL [CANCELADO]
Essa rotina só funciona em um método declarado na seção published, correto? Em 19 de julho de 2010 20:27, Roni Rodrigo ronirodr...@yahoo.com.brescreveu: cara... eu utilizo a RTTI pra fazer chamadas a métodos da classe... para manipular os métodos e propriedades eu utilizo helpers para as classes da RTTI... se eu não me engano funciona com os métodos de qualquer escopo (ou menos da strict private.. não tenho certeza)... na verdade esse código eu achei na internet.. no site da embarcadero mesmo... mas agora não consegui achar pra passar o link.. então vou colocar o exemplo de como eu utilizo aqui --- Uses TypInfo, ObjAuto, uRClassProperties; type // declara os helpers para a RTTI TParamInfoHelper = record helper for TParamInfo public function AsString: string; function NextParam: PParamInfo; end; TReturnInfoHelper = record helper for TReturnInfo public function AsString: string; end; TMethodInfoHeaderHelper = record helper for TMethodInfoHeader private function GetReturnInfo: PReturnInfo; public property ReturnInfo: PReturnInfo read GetReturnInfo; end; TObjectHelper = class helper for TObject public function RTTIMethodsAsString: string; end; function DescriptionOfMethod( Obj: TObject; MethodName: string ): string; implementation uses SysUtils; const SHORT_LEN = sizeof(ShortString) - 1; function DescriptionOfMethod( Obj: TObject; MethodName: string ): string; var header: PMethodInfoHeader; headerEnd: Pointer; Params, Param: PParamInfo; returnInfo: PReturnInfo; begin header := ObjAuto.GetMethodInfo( Obj, MethodName ); if Header.Len = SizeOf(TMethodInfoHeader) - SHORT_LEN + Length(Header.Name) then begin Result := 'No rich RTTI'; exit; end; headerEnd := Pointer(Integer(header) + header^.Len); Params := PParamInfo(Integer(header) + SizeOf(header^) - SHORT_LEN + SizeOf(TReturnInfo) + Length(header^.Name)); Param := Params; Result := ''; while Integer(Param) Integer(headerEnd) do begin Result := Result + Param.AsString + '; '; Param := Param.NextParam; end; Delete( Result, Length(Result)-1,2 ); returnInfo := header.ReturnInfo; if assigned( returnInfo.ReturnType ) then Result := Format( 'function %s( %s ): %s', [ MethodName, Result, returnInfo.AsString ] ) else Result := Format( 'procedure %s( %s )%s', [ MethodName, Result, returnInfo.AsString ] ); end; { TParamInfoHelper } function TParamInfoHelper.AsString: string; begin Result := ''; if pfResult in Flags then exit; Result := Name + ': ' + ParamType^.Name; if pfVar in self.Flags then Result := 'var ' + Result; end; function TParamInfoHelper.NextParam: PParamInfo; begin Result := PParamInfo(Integer(@self) + SizeOf(self) - SHORT_LEN + Length(Name)); end; { TMethodInfoHeaderHelper } function TMethodInfoHeaderHelper.GetReturnInfo: PReturnInfo; begin Result := PReturnInfo(Integer(@self) + SizeOf(TMethodInfoHeader) - SHORT_LEN + Length(Name)); end; { TReturnInfoHelper } function TReturnInfoHelper.AsString: string; var c: string; begin Assert( Version = 1, 'Version of ReturnInfo incorrect' ); if assigned( ReturnType ) then Result := ReturnType^.Name; Result := Result + ';'; case CallingConvention of ccRegister: ;// Default ccCdecl: c := 'cdecl'; ccPascal: c := 'pascal'; ccStdCall: c := 'stdcall'; ccSafeCall: c := 'safecall'; end; if c '' then Result := Result + ' ' + c + ';'; end; { TObjectHelper } function TObjectHelper.RTTIMethodsAsString: string; var MethodInfo: Pointer; Count: Integer; method: PMethodInfoHeader; i: Integer; begin MethodInfo := PPointer(Integer(PPointer(self)^) + vmtMethodTable)^; if MethodInfo nil then begin Count := PWord(MethodInfo)^; Inc(Integer(MethodInfo), 2); method := MethodInfo; for i := 0 to Count - 1 do begin Result := Result + DescriptionOfMethod(self, method.Name) + sLineBreak; Inc(Integer(method), PMethodInfoHeader(method)^.Len); end; end; end; -- feito isso, adicione essa unit a Uses que irá fazer as chamadas... e utilize normalmente os métodos da RTTI para recuperar as informacoes do objeto em um TreeView, por exemplo: --- procedure GenerateNodes(Obj: TObject; Node: TTreeNode); var i: byte; InternalNode1, InternalNode2, InternalNode3: TTreeNode; PropList: PPropList; PropListCount: byte; MethodInfo: Pointer; MethodListCount: byte; Method: PMethodInfoHeader; begin if Assigned(Node) then InternalNode1 := Node else InternalNode1 := TreeView1.Items.Add(nil, Obj.ClassName); //Propriedades InternalNode2 := TreeView1.Items.AddChild( InternalNode1, 'Propriedades'); PropListCount := GetPropList(Obj, PropList); for i := 0 to Pred(PropListCount) do begin InternalNode3 := TreeView1.Items.AddChild(InternalNode2, string(PropList[i].Name) + '=' + QuotedStr( string( GetPropValue( Obj, string(Proplist[i].Name) ) ) ) ); if PropType(Obj, string( PropList[i].Name )) =
Re: [delphi-br] Re: MethodAddress retornando NIL [CANCELADO]
cara... eu utilizo a RTTI pra fazer chamadas a métodos da classe... para manipular os métodos e propriedades eu utilizo helpers para as classes da RTTI... se eu não me engano funciona com os métodos de qualquer escopo (ou menos da strict private.. não tenho certeza)... na verdade esse código eu achei na internet.. no site da embarcadero mesmo... mas agora não consegui achar pra passar o link.. então vou colocar o exemplo de como eu utilizo aqui --- Uses TypInfo, ObjAuto, uRClassProperties; type // declara os helpers para a RTTI TParamInfoHelper = record helper for TParamInfo public function AsString: string; function NextParam: PParamInfo; end; TReturnInfoHelper = record helper for TReturnInfo public function AsString: string; end; TMethodInfoHeaderHelper = record helper for TMethodInfoHeader private function GetReturnInfo: PReturnInfo; public property ReturnInfo: PReturnInfo read GetReturnInfo; end; TObjectHelper = class helper for TObject public function RTTIMethodsAsString: string; end; function DescriptionOfMethod( Obj: TObject; MethodName: string ): string; implementation uses SysUtils; const SHORT_LEN = sizeof(ShortString) - 1; function DescriptionOfMethod( Obj: TObject; MethodName: string ): string; var header: PMethodInfoHeader; headerEnd: Pointer; Params, Param: PParamInfo; returnInfo: PReturnInfo; begin header := ObjAuto.GetMethodInfo( Obj, MethodName ); if Header.Len = SizeOf(TMethodInfoHeader) - SHORT_LEN + Length(Header.Name) then begin Result := 'No rich RTTI'; exit; end; headerEnd := Pointer(Integer(header) + header^.Len); Params := PParamInfo(Integer(header) + SizeOf(header^) - SHORT_LEN + SizeOf(TReturnInfo) + Length(header^.Name)); Param := Params; Result := ''; while Integer(Param) Integer(headerEnd) do begin Result := Result + Param.AsString + '; '; Param := Param.NextParam; end; Delete( Result, Length(Result)-1,2 ); returnInfo := header.ReturnInfo; if assigned( returnInfo.ReturnType ) then Result := Format( 'function %s( %s ): %s', [ MethodName, Result, returnInfo.AsString ] ) else Result := Format( 'procedure %s( %s )%s', [ MethodName, Result, returnInfo.AsString ] ); end; { TParamInfoHelper } function TParamInfoHelper.AsString: string; begin Result := ''; if pfResult in Flags then exit; Result := Name + ': ' + ParamType^.Name; if pfVar in self.Flags then Result := 'var ' + Result; end; function TParamInfoHelper.NextParam: PParamInfo; begin Result := PParamInfo(Integer(@self) + SizeOf(self) - SHORT_LEN + Length(Name)); end; { TMethodInfoHeaderHelper } function TMethodInfoHeaderHelper.GetReturnInfo: PReturnInfo; begin Result := PReturnInfo(Integer(@self) + SizeOf(TMethodInfoHeader) - SHORT_LEN + Length(Name)); end; { TReturnInfoHelper } function TReturnInfoHelper.AsString: string; var c: string; begin Assert( Version = 1, 'Version of ReturnInfo incorrect' ); if assigned( ReturnType ) then Result := ReturnType^.Name; Result := Result + ';'; case CallingConvention of ccRegister: ;// Default ccCdecl: c := 'cdecl'; ccPascal: c := 'pascal'; ccStdCall: c := 'stdcall'; ccSafeCall: c := 'safecall'; end; if c '' then Result := Result + ' ' + c + ';'; end; { TObjectHelper } function TObjectHelper.RTTIMethodsAsString: string; var MethodInfo: Pointer; Count: Integer; method: PMethodInfoHeader; i: Integer; begin MethodInfo := PPointer(Integer(PPointer(self)^) + vmtMethodTable)^; if MethodInfo nil then begin Count := PWord(MethodInfo)^; Inc(Integer(MethodInfo), 2); method := MethodInfo; for i := 0 to Count - 1 do begin Result := Result + DescriptionOfMethod(self, method.Name) + sLineBreak; Inc(Integer(method), PMethodInfoHeader(method)^.Len); end; end; end; -- feito isso, adicione essa unit a Uses que irá fazer as chamadas... e utilize normalmente os métodos da RTTI para recuperar as informacoes do objeto em um TreeView, por exemplo: --- procedure GenerateNodes(Obj: TObject; Node: TTreeNode); var i: byte; InternalNode1, InternalNode2, InternalNode3: TTreeNode; PropList: PPropList; PropListCount: byte; MethodInfo: Pointer; MethodListCount: byte; Method: PMethodInfoHeader; begin if Assigned(Node) then InternalNode1 := Node else InternalNode1 := TreeView1.Items.Add(nil, Obj.ClassName); //Propriedades InternalNode2 := TreeView1.Items.AddChild( InternalNode1, 'Propriedades'); PropListCount := GetPropList(Obj, PropList); for i := 0 to Pred(PropListCount) do begin InternalNode3 := TreeView1.Items.AddChild(InternalNode2, string(PropList[i].Name) + '=' +