Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.02.29;
Скачать: CL | DM;

Вниз

Как сравнить две переменные типа TNotifyEvent?   Найти похожие ветки 

 
Defunct ©   (2004-02-15 23:35) [0]

Как получить имя/адрес владельца метода имея адрес метода?
Вот привожу простенький фрагмент программы, F1, F2 назначется один и тот же метод одного и того же класса, разных екземпляров. Теоретически F1<>F2, как это проверить? При запуске фрагмента, на экран выводится A1=A2.


...
TMyComponent = Class
X : Cardinal;
Constructor Create;Virtual;
Procedure StepForward(Sender:TObject);virtual;
End;

var F1,F2:TNotifyEvent;
A1,A2:Pointer;
C1,C2:TMyComponent;

Impementation

Constructor TMyComponent.Create;
Begin
End;

Procedure TMyComponent.StepForward;
Begin
Inc(X);
End;

procedure TForm1.FormCreate(Sender: TObject);
begin
C1 := TMyComponent.Create;
C2 := TMyComponent.Create;
F1:=C1.StepForward;
F2:=C2.StepForward;

A1:=Addr(F1);
A2:=Addr(F2);
If A1<>A2 then Application.MessageBox("A1<>A2","A1<>A2")
else Application.MessageBox("A1=A2","A1=A2");
end;
...


Дополение к вопросу:
http://delphimaster.net/view/1-1076871235/

2 модератор: просьба не закрывать обсуждение.


 
Palladin ©   (2004-02-15 23:53) [1]


> Как получить имя/адрес владельца метода имея адрес метода?

никак... метод принадлежит классу а не объекту.


 
Юрий Зотов ©   (2004-02-16 00:02) [2]

> Palladin © (15.02.04 23:53) [1]

Это верно, но ведь Self откуда-то берется?
:о)

> Defunct © (15.02.04 23:35)

TMethod.Data - указывает на экземпляр объекта, для которого вызывается данный метод (а Code дает адрес самого метода).

type
TMyComponent = class(TComponent)
public
procedure StepForward(Sender: TObject); virtual;
end;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;

var
Form1: TForm1;

procedure TMyComponent.StepForward(Sender: TObject);
begin
//
end;

procedure TForm1.Button1Click(Sender: TObject);
var
F1, F2: TNotifyEvent;
begin
F1 := TMyComponent.Create(Self).StepForward;
F2 := TMyComponent.Create(Self).StepForward;
Caption := Format("$%x $%x", [Integer(TMethod(F1).Data), Integer(TMethod(F2).Data)])
end;


 
Defunct ©   (2004-02-16 00:11) [3]

Большое спасибо!


 
Юрий Зотов ©   (2004-02-16 00:12) [4]

Вот так будет более наглядно:

procedure TMyComponent.StepForward(Sender: TObject);
begin
ShowMessage(Format("$%x", [Integer(Self)]))
end;

procedure TForm1.Button1Click(Sender: TObject);
var
F1, F2: TNotifyEvent;
begin
F1 := TMyComponent.Create(Self).StepForward;
F2 := TMyComponent.Create(Self).StepForward;
Caption := Format("$%x $%x", [Integer(TMethod(F1).Data), Integer(TMethod(F2).Data)]);
F1(nil); // Сравните число в ShowMessage c первым числом в Caption
F2(nil); // Сравните число в ShowMessage cо вторым числом в Caption
end;


 
Palladin ©   (2004-02-16 00:15) [5]


> Юрий Зотов © (16.02.04 00:02) [2]

:) передается при вызове...
если чесно я не допонял, что пытается сделать автор в вышеуказанном коде... self всегда доступен в теле метода, а сравнивать указатели на метод на предмет равности... хем... странное дело...
Буду очень рад если приведете пример практики использования TMethod.Data


 
Defunct ©   (2004-02-16 00:20) [6]

Да да, эта часть уже сама собой понятна. Раз получили адрес Self, они будут идентичны.

ключ был здесь,
struct TMethod
{
void *Code;
void *Data;
};

еще раз, огромное спасибо за пример


 
Defunct ©   (2004-02-16 00:22) [7]

Palladin © (16.02.04 00:15) [5]
Буду очень рад если приведете пример практики использования TMethod.Data
привожу:
http://delphimaster.net/view/1-1076871235/

В двух словах - список событий с временами запуска. Фильтрация одинаковых событий в очереди событий


 
Юрий Зотов ©   (2004-02-16 00:36) [8]

> Palladin © (16.02.04 00:15) [5]

> self всегда доступен в теле метода

Это да, и мы даже знаем, что он передается неявным параметром. Но зададим себе вопрос - а ОТКУДА компилятор берет значение этого параметра при формировании кода вызова?

> пример практики использования TMethod.Data

Эмуляция событий. В проекте, где я сейчас участвую, используется на всю катушку.


 
Palladin ©   (2004-02-16 00:55) [9]

Спасибо, надо будет взять на заметку это дело.


 
Юрий Зотов ©   (2004-02-16 01:11) [10]

> Palladin © (16.02.04 00:55) [9]

Кстати - таким же образом можно назначить обработчиком события обычную процедуру вместо метода объекта.

procedure Proc(Self, Sender: TObject);
begin
ShowMessage(Self.ClassName)
end;

var
B: TButton;
M: TMethod;
begin
B := TButton.Create(nil);
try
M.Code := @Proc;
M.Data := B;
SetMethodProp(B, "OnClick", M); // uses TypInfo
B.Click
finally
B.Free
end
end;


 
Palladin ©   (2004-02-16 02:31) [11]

Про этот финт я в курсе :) Вот чего не увидел так это практической ценности в TMethod и при разработке не использовал никогда. Не те задачи, однако...


 
Defunct ©   (2004-02-16 04:06) [12]

Хм.. получается при создании процедурного типа

F = Procedure(Param1:..;Param2:..;.. ParamN:ParamType);

создается

Record
Code : Pointer;
Param1 : ..
Param2 : ..
..
ParamN : ParamType;
End;

Причем полей как таковых нет, они будут загружены в стек на момент запуска процедуры.

А если это будет..
Procedure Of Object
То в Record добавляется поле Data:Pointer;

Мда, теперь понятно почему неполучилось найти разницу при таком сравнении:


TMyComponent = Class
Constructor Create;Virtual;
Procedure StepForward(Sender:TObject);Virtual;
End;

MyArray = Array[1..2] of DWord;

Var
P1,P2 : ^MyArray;
F1,F2 : TNotifyEvent;

Constructor TMyComponent.Create;
Begin
End;

Procedure TMyComponent.StepForward;
Begin
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
F1 := TMyComponent.Create.StepForward;
F2 := TMyComponent.Create.StepForward;

P1 := @F1;
P2 := @F2;

Caption := Format("%x:%x %x:%x",[P1^[1],P1^[2], P2^[1],P2^[2]]);
end;


Все же интересно, из какого источника компилятор заполняет поля Data.


 
Alex Konshin ©   (2004-02-16 08:50) [13]

Он передается как неявный первый параметр.
Так как первый параметр передается в регистре EAX (не будетм углубляться в разные модели вызовов), то, соответственно, он там обычно и находится на входе в процедуру.

Могу привести еще один пример использования TMethod - вызов метода прародителя в обход перекрытия этого метода родителем.
Иногда это нужно.
Еще одно применение - реализация подобия reflection из Java, то вызов метода по имени.


 
pasha_golub ©   (2004-02-16 09:24) [14]

Alex Konshin © (16.02.04 08:50) [13]

Приведите, приведите. Очень интересно.


 
MBo ©   (2004-02-16 09:35) [15]

>pasha_golub
type
C1 = class
procedure Method1;virtual;
end;

type
C2 = class(C1)
procedure Method1;override;
end;

type
C3 = class(C2)
procedure Method1;override;
end;

procedure C3.Method1;
type
tproc=procedure of object;
var
m:tmethod;
begin
m.code:=@c1.method1;
m.data:=self;
TProc(m);
end;


 
Alex Konshin ©   (2004-02-16 09:50) [16]

Фантазии не хватает?
Собственно, вызов ничем не отличается от вызова другого метода.


var
method : TMethod;

...

with TMethod(method) do
begin
Code := @TGrandParent.SomeMethod;
Data := Self;
end;

...

method(...);



 
Alex Konshin ©   (2004-02-16 09:53) [17]

MBo © (16.02.04 09:35) [15]
TProc не нужен.


 
Alex Konshin ©   (2004-02-16 09:55) [18]

Упс, был неправ.
Нужно было в объявлении написать так:
type
TProc = procedure(...) of object;
var
method : TProc; // :) ну пусть будет так


 
pasha_golub ©   (2004-02-16 10:01) [19]

MBo © (16.02.04 09:35) [15]
Alex Konshin © (16.02.04 09:53) [17]

Спасибо, уже видел. А не чревато ли это?


 
Alex Konshin ©   (2004-02-16 10:08) [20]

Чем чревато? Естественно, нужно понимать, что ты делаешь.


 
pasha_golub ©   (2004-02-16 10:10) [21]

Alex Konshin © (16.02.04 10:08) [20]
Иногда одним пониманием от беды не спасешься. :-)



Страницы: 1 вся ветка

Текущий архив: 2004.02.29;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.03 c
4-94232
konstantinov
2003-12-22 20:30
2004.02.29
Диалоговые окна средствами API


1-94012
heady
2004-02-16 17:49
2004.02.29
Активная ссылка


6-94052
alexEagle
2003-12-24 15:09
2004.02.29
Как узнать что сервер (TServerSocket) закрыл соединение?


1-93981
Aliev
2004-02-17 12:27
2004.02.29
Как делать что все формы были на таскбаре?


14-94117
Игорь Досужев
2004-02-08 23:52
2004.02.29
rsdn.ru в дауне?