Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

method pointer ВМЕСТО regular procedure?


Timego ©   (2004-10-07 15:48:00) 

Есть некая функция, которая в качестве параметра требует указатель на коллбэк функцию.

procedure CreateSmth(ACallBack: PCallBack),
где
PCALLBACK = procedure(...) stdcall;

Возникла огромная необходимость передать в CreateSmth метод класса вместо ссылки на глобальную процедуру типа PCallBack.

Компилятор, конечно, не дал этого сделать, резонно указав, что "Incompatible types: method pointer and regular procedure". Это я и без него знал, но где-то настраницах FAQ или этого форума я видел подсказку о хитром (или не очень) способе обойти это недрозумение и все-таки передавать в CreateSmth метод класса.

Буду благодаен за помощь!


the   (2004-10-07 17:58:00) [1]

>DiamondShark ©   (07.10.04 16:37) [8]

В случае, когда помимо ф-и передётся ещё и пользовательский
указатель, который идет первымаргументом колбэк ф-и, можно вообще не использовать заглушки, а сразу использовать прямо метод как указатель на простую ф-ю (TMethod.Code)

TTest = class
 procedure CallBack( (* Contex = Self *) ...); stdcall;
 // сам по себе медод - это по сути процедура с дополнительным
 // аргументом Self.
end;

TCallBackMeth = procedure (...)of object; stdcall;
TCallBackProc = procedure (Context: Pointer; ...); stdcall;

m: TCallBackMeth;
test: TTest;
...
m := test.CallBack;
CreateSmth(TCallBackProc(TMethod(m).Code), TMethod(m).Data);
//CreateSmth(TCallBackProc(@TTest.CallBack), Pointer(test));

// Но в ф-и, которой передаётся колбэк ф-я, должен одновременно
// передаваться и пользовательский указатель.
// если это не так, то поможет только аналог
// MakeObjectInstance


Суслик   (2004-10-07 16:39:00) [2]


>  [8] DiamondShark ©   (07.10.04 16:37)

давай спорить не будем - ясно что методов до фига и больше.


DiamondShark   (2004-10-07 16:37:00) [3]


> тогда надо знать какой метод. у?

Кю.
А методов сотня что-ли?
А хоть бы и сотня. На каждый метод -- заглушка вида:

procedure CallBackA(Context: Pointer; ...);
begin
 TMyClass(Context).MethodA(...)
end;
procedure CallBackB(Context: Pointer; ...);
begin
 TMyClass(Context).MethodB(...)
end;


> вооще судя по описанию callback параметр acontext скорее
> делает именно то, о чем я говорю.

Ну дык. Полагаться на телепатические способности становится уже доброй практикой ;)


Суслик   (2004-10-07 16:25:00) [4]

вооще судя по описанию callback параметр acontext скорее делает именно то, о чем я говорю.


Суслик   (2004-10-07 16:24:00) [5]

тогда надо знать какой метод. у?


DiamondShark   (2004-10-07 16:23:00) [6]


> В этих 4х байтах можно передать адрес записи, содержащей
> метод переданный в CreateSmth

В этих 4х байтах можно передать указатель на экземпляр, чей метод надо вызвать. Ы?


Суслик   (2004-10-07 16:12:00) [7]

Есть еще вариант.
Многие фукнции кроме callback повзволяют еще передать 4 байта, которые фукнция переправит в callback. В этих 4х байтах можно передать адрес записи, содержащей метод переданный в CreateSmth. В callback вывывать этот метод. Это позволит обойтись без глобальных переменных.


Суслик   (2004-10-07 16:04:00) [8]

1. просто так сделать и передать метод вместо процедуры нельзя, т.к. процедурный тип есть 4 байта (pointer), а тип-метод - 8 байт (адрес объекта и метода в нем).

2. Если тебе нужно передавать  в CreateSmth метод, то и передавай метод.

3. Насколько я понимаю, дальше тебе необходимо передать этот метод в некую функцию (предполагаю, что НЕ твоей разработки).

4. Нет ничего проще. Описываешь callback как раньше (т.е. глобальную процедуру). Описываешь глоб. перем. в которую в методе CreateSmth запсываешь переданный ей метод. В callback пишешь вызов метода из глобальной переменной.

т.е. примерно так.

TMet = procedure of object;

var
   M: TMet;

procedure Callback(
  const ANUMBER : CNUMBER;
  AContext, ASpecial1, ASpecial2 : Pointer) stdcall;
begin
  M();
end;

procedure CreateSmth(aM: TMet);
begin
  M := aM;
  FuntThatNeedsCallback(Callback);
end;


Timego   (2004-10-07 15:58:00) [9]


> Это не оконная процедура случаем?


Нет, это не оконная процедура ни в коем случае. Описана так:

 PCALLBACK = procedure(
   const ANUMBER : CNUMBER;
   AContext, ASpecial1, ASpecial2 : Pointer) stdcall;

где

 CNUMBER =
 (
   CN_ADD,
   CN_REMOVE, ...


Суслик   (2004-10-07 15:50:00) [10]

Давай сначала определимся с тем, как описан callback?

приведи описание?

Это не оконная процедура случаем?


Наверх

Титульная страница Поиск, карта сайта Написать письмо