Re: [delphi-br] Re: MethodAddress retornando NIL [CANCELADO]

2010-07-21 Por tôpico Roni Rodrigo
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]

2010-07-21 Por tôpico Roni Rodrigo
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]

2010-07-20 Por tôpico Fabricio Colombo
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]

2010-07-19 Por tôpico Roni Rodrigo
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) + '=' +