Текущий архив: 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.47 MB
Время: 0.054 c