![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Попытка доступа к методам класса [D7, Win2k]
Юрий_К © (2007-01-11 19:28:00)http://www.clubdelphi.com/foros/archive/index.php/t-32526.html
Нашёл в сети код (линк дал выше) :
unit PubMeth;
interface
uses
Classes, TypInfo;
type
PVmtMethod = ^TVmtMethod;
TVmtMethod = packed record
Size: Word;
Address: Pointer;
Name: ShortString;
end;
PVmtMethodTable = ^TVmtMethodTable;
TVmtMethodTable = packed record
Count: Word;
Methods: array [0..MaxListSize] of byte;
{ Methods : array [0..Count] of TVmtMethod;}
end;
TPublishedMethodIterator = class
private
FVMT: Pointer;
FMethodTable: PVmtMethodTable;
FCurrent: PVmtMethod;
FCurrentIndex: Integer;
function CurrentLength: Integer;
public
property VMT: Pointer read FVMT;
property Current: PVmtMethod read FCurrent;
function GetMethodCount: Integer;
procedure Init(AClass: TClass);
function First: PVmtMethod;
function Next: PVmtMethod;
end;
function OffsetPtr(P: Pointer; Offset: Integer): Pointer;
implementation
function OffsetPtr(P: Pointer; Offset: Integer): Pointer;
begin
Integer(Result) := Integer(P) + OffSet;
end;
{ TPublishedMethodIterator }
function TPublishedMethodIterator.GetMethodCount: Integer;
begin
Result := 0;
if not Assigned(FMethodTable) then Exit;
Result := FMethodTable^.Count;
end;
procedure TPublishedMethodIterator.Init(AClass: TClass);
begin
FMethodTable := nil;
FVMT := Pointer(AClass);
FMethodTable := Pointer( OffsetPtr(FVMT, vmtMethodTable)^ );
FCurrent := nil;
end;
function TPublishedMethodIterator.First: PVmtMethod;
begin
Result := nil;
FCurrentIndex := 0;
if not Assigned(FMethodTable) then Exit;
FCurrent := Pointer(@FMethodTable.Methods[0]);
Result := FCurrent;
end;
function TPublishedMethodIterator.CurrentLength: Integer;
begin
Result := 0;
if not Assigned(FCurrent) then Exit;
Result := Current^.Size; // SizeOf(Word) + SizeOf(Pointer) + Length(Current^.Name) + 1;
end;
function TPublishedMethodIterator.Next: PVmtMethod;
begin
Result := nil;
if not Assigned(FMethodTable) then Exit;
if FCurrentIndex + 1 >= GetMethodCount then
begin
FCurrent := nil;
end
else
begin
FCurrent := OffsetPtr(FCurrent, CurrentLength);
Inc(FCurrentIndex);
end;
Result := FCurrent;
end;
end.
Использовал так:
procedure TForm1.Button1Click(Sender: TObject);
var
MethodIterator: TPublishedMethodIterator;
Cls: TClass;
begin
re2.Clear;
MethodIterator := TPublishedMethodIterator.Create;
Cls := Sender.ClassType;
try
with MethodIterator do
begin
while Cls <> nil do
begin
Init(Cls);
re2.Lines.Add(Format('%s, %d methods',[TClass(VMT).ClassName, GetMethodCount]));
First;
while (Current <> nil) do
begin
re2.Lines.Add(Format(' %s: $%p',[Current^.Name, Current^.Address]));
Next;
end;
Cls := Cls.ClassParent;
end;
end;
finally
MethodIterator.Free;
end;
Что получил:
"
TButton, 0 methods
TButtonControl, 0 methods
TWinControl, 0 methods
TControl, 0 methods
TComponent, 0 methods
TPersistent, 0 methods
TObject, 0 methods
"
Что же, у всех этих классов кол-во публичных методов равно нулю?
Или что-то тут не так?
Бурундук (2007-01-12 11:50:00) [21]2Юрий_К (12.01.07 11:40) [9]
>Использование кода было в
>"procedure TForm1.Button1Click(Sender: TObject);".
>Почему хотя бы этот Button1Click в таком случае не посчитался?
>Может он динамический?
Какая разница, откуда ты вызвал код?
Чтобы увидеть Button1Click, тебе нужно смотреть
опубликованные методы класса TForm1,
а ты смотрел методы класса TButton.
Если хочешь увидеть Button1Click, поменяй
Cls := Sender.ClassType;
на
Cls := Self.ClassType;
Юрий_К (2007-01-12 11:43:00) [22]Не совсем полностью скопировал выше:
"
VMT=0042348C
Destroy=00412D70
FreeInstance=004029B8
NewInstance=00402990
DefaultHandler=00413EF0
InstanceSize=264
ClassParent=TButtonControl (004233D8)
ClassName=TButton
ClassInfo=00423568
DynMethodTable=00423540
Count: 5
Dyn Method 0=00425DB8 (B005)
Dyn Method 1=00425E20 (B006)
Dyn Method 2=00425EA0 (B007)
Dyn Method 3=00425DA4 (BD11)
Dyn Method 4=00425CA8 (-11)
MethodTable=00000000
FieldTable=00000000
InitTable=00000000
AutoTable=00000000
"
Юрий_К (2007-01-12 11:40:00) [23]Бурундук © (11.01.07 22:37) [2]
"Разумеется, равно нулю.
Публичные методы используются в основном для обработчиков событий,
всяких Form1Create, Button1Click и т.п."
Использование кода было в "procedure TForm1.Button1Click(Sender: TObject);".
Почему хотя бы этот Button1Click в таком случае не посчитался? Может он динамический?
VMTDemo (Delphi2) от Рэя Лишнера даёт
"
VMT=0042348C
Destroy=00412D70
FreeInstance=004029B8
NewInstance=00402990
DefaultHandler=00413EF0
InstanceSize=264
ClassParent=TButtonControl (004233D8)
ClassName=TButton
ClassInfo=00423568
DynMethodTable=00423540
Count: 5
Dyn Method 0=00425DB8 (B005)
Dyn Method 1=00425E20 (B006)
Dyn Method 2=00425EA0 (B007)
"
procedure WriteVmtInfo(ClassType: TClass);
var
Vmt: PVmt;
begin
Vmt := PVmt(ClassType);
Dec(Vmt, 1);
FmtLn('VMT=%p', [Vmt]);
FmtLn(' Destroy=%p', [Vmt^.Destroy]);
FmtLn(' FreeInstance=%p', [Vmt^.FreeInstance]);
FmtLn(' NewInstance=%p', [Vmt^.NewInstance]);
FmtLn(' DefaultHandler=%p', [Vmt^.DefaultHandler]);
FmtLn(' InstanceSize=%d', [Vmt^.InstanceSize]);
if Vmt^.ClassParent = nil then
WriteLn(' ClassParent=nil')
else
FmtLn(' ClassParent=%s (%p)', [Vmt^.ClassParent.ClassName, Pointer(Vmt^.ClassParent)]);
WriteLn(' ClassName=', GetClassName(Vmt)^);
{$ifdef WIN32}
FmtLn(' ClassInfo=%p', [Vmt^.TypeInfo]);
{$else}
FmtLn(' ClassInfo=%x', [Vmt^.TypeInfo]);
{$endif}
{$ifdef WIN32}
FmtLn(' DynMethodTable=%p', [Vmt^.DynMethodTable]);
{$else}
FmtLn(' DynMethodTable=%x', [Vmt^.DynMethodTable]);
{$endif}
if Vmt^.DynMethodTable <> VmtNil then
WriteDynMethods(Vmt);
{$ifdef WIN32}
FmtLn(' MethodTable=%p', [Vmt^.MethodTable]);
{$else}
FmtLn(' MethodTable=%x', [Vmt^.MethodTable]);
{$endif}
if Vmt^.MethodTable <> VmtNil then
WriteMethods(GetMethodTable(Vmt));
{$ifdef WIN32}
FmtLn(' FieldTable=%p', [Vmt^.FieldTable]);
{$else}
FmtLn(' FieldTable=%x', [Vmt^.FieldTable]);
{$endif}
if Vmt^.FieldTable <> VmtNil then
WriteFields(GetFieldTable(Vmt));
{$ifndef VER80}
FmtLn(' InitTable=%p', [Vmt^.InitTable]);
if Vmt^.InitTable <> nil then
WriteInitTable(GetInitTable(Vmt));
FmtLn(' AutoTable=%p', [Vmt^.AutoTable]);
if Vmt^.AutoTable <> nil then
WriteAutoTable(GetAutoTable(Vmt));
{$endif}
end;
Джо (2007-01-12 10:16:00) [24]> Бурундук
Гм. И автор вопрос тоже «описался»? Или «был введен в заблуждение»? Желательно было бы определиться и автору вопроса и автору кода :)
Бурундук (2007-01-12 10:15:00) [25]Вы слушайте, что я имею ввиду, а не то, что я говорю!
(с) Фейнман
Бурундук (2007-01-12 10:05:00) [26]Джо © (12.01.07 05:44) [5]
описался, блин. Опубликованных, конечно.
Джо (2007-01-12 05:44:00) [27]> [2] Бурундук © (11.01.07 22:37)
> Юрий_К (11.01.07 19:28)
> Что же, у всех этих классов кол-во публичных методов равно
> нулю?
>
> Разумеется, равно нулю.
TButton = class(TButtonControl)Не считая предков, там вообще море.
public
constructor Create(AOwner: TComponent); override;
procedure Click; override;
function UseRightToLeftAlignment: Boolean; override;
end;
Anatoly Podgoretsky (2007-01-12 02:16:00) [28]> GrayFace (12.01.2007 02:14:03) [3]
Зато published так не переводится.
GrayFace (2007-01-12 02:14:00) [29]Точнее, нет published методов. Public тоже переводится как публичный.
Бурундук (2007-01-11 22:37:00) [30]Юрий_К (11.01.07 19:28)
Что же, у всех этих классов кол-во публичных методов равно нулю?
Разумеется, равно нулю.
Публичные методы используются в основном для обработчиков событий,
всяких Form1Create, Button1Click и т.п.
PS код, кстати, мой.
vlad-mal (2007-01-11 20:12:00) [31]
> http://www.clubdelphi.com/foros/archive/index.php/t-32526.
> htmlНашёл в сети код (линк дал выше) :
Обрати внимание на это:
En el artículo Run-Time Type Information (RTTI) in Delphi ( http://www.blong.com/Conferences/BorConUK98/DelphiRTTI/CB140.htm), de Brian Long ( http://www.blong.com/), se explica bastante bien cómo puede obtenerse información sobre tipos en tiempo de ejecución. No os perdáis el resto de documentación disponible en la página Web de Brian Long.