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

Вниз

method pointer ВМЕСТО regular procedure?   Найти похожие ветки 

 
Timego   (2004-10-07 15:48) [0]

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

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

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

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

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


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

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

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

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


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


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


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

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

где

 CNUMBER =
 (
   CN_ADD,
   CN_REMOVE, ...


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

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;


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

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


 
DiamondShark ©   (2004-10-07 16:23) [5]


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

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


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

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


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

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


 
DiamondShark ©   (2004-10-07 16:37) [8]


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

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

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


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

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


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


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

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


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

>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



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

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

Наверх




Память: 0.49 MB
Время: 0.057 c
1-1097521677
DronVelikii
2004-10-11 23:07
2004.10.24
Передача динамического массива в DLL


1-1097406315
SNV-Soft
2004-10-10 15:05
2004.10.24
Как заставить работать OnMouseMove у панели!?


14-1096682053
Думкин
2004-10-02 05:54
2004.10.24
С днем рождения! 2 октября


8-1089041318
Сергей Г
2004-07-05 19:28
2004.10.24
Конвертация музыкальных файлов


6-1092410075
Дмитрий Ботвин
2004-08-13 19:14
2004.10.24
Тип запуска службы