Представление Callback функции как метода класса

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Представление Callback функции как метода класса

Сообщение immortal1977 » 13.03.2009 15:24:42

Уважаемые форумчане. Уже много дней мучаюсь, даже спать не могу. Интересует простой вопрос, но ответа пока не у кого не получил - как мне представить метод класса как callback функцию с модификатором stdcall, что бы винда смогла вызывать ее, но при этом рождение нескольких экземпляров класса гарантировало бы рождение нескольких, независимых по памяти callback ф-ций.

P.S. отсюда возникает очень не хорошее следствие, неужели если программа пишется на чистом api, и необходимо породить скажем 10 однотипных тридов, то необходимо сваять 10 одинаковых callback TreadProc. Возможен ли массив одинаковых callback proc?
immortal1977
новенький
 
Сообщения: 16
Зарегистрирован: 14.07.2008 15:52:23
Откуда: Новоуральск

Re: Представление Callback функции как метода класса

Сообщение zub » 13.03.2009 16:09:59

Если в callback приходит чтото уникальное - типа HWND для окон, можно по нему находить свой класс и вызывать соответствующий метод
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Представление Callback функции как метода класса

Сообщение Sergei I. Gorelkin » 13.03.2009 17:00:15

callback функция - это "обычная" процедура, ее невозможно представить как метод класса. Нужно писать по крайней мере переходник, который уже будет вызывать нужный метод.
В WinAPI в большинстве случаев callback-функции имеют пользовательский параметр (lparam), в котором очень удобно передавать указатель на нужный объект.
В случае с оконной процедурой (WndProc) такого параметра нет, приходится изобретать нечто альтернативное. Можно либо использовать хеш-таблицу соответствия HWND<->объект (TBucketList подходит), либо цеплять указатель на объект к окну с помощью SetProp().
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Представление Callback функции как метода класса

Сообщение Bupyc » 13.03.2009 17:14:21

Как уже было сказано,

callback функция - это "обычная" процедура, ее невозможно представить как метод класса. Нужно писать по крайней мере переходник, который уже будет вызывать нужный метод.


ибо как пишет дельфёвый хелп:

A method pointer is really a pair of pointers; the first stores the address of a method, and the second stores a reference to the object the method belongs to.


Как я понимаю, последнее утверждение актуально не только для дельфи, но и для FPC.
Bupyc
постоялец
 
Сообщения: 137
Зарегистрирован: 29.08.2007 18:22:42

Re: Представление Callback функции как метода класса

Сообщение immortal1977 » 13.03.2009 18:09:34

Спасибо за ответы. От себя добавлю, что после долгого гугления, нашел таки исходник переходника class method <-> procedure.

Все таки оно существует...
immortal1977
новенький
 
Сообщения: 16
Зарегистрирован: 14.07.2008 15:52:23
Откуда: Новоуральск

Re: Представление Callback функции как метода класса

Сообщение Дож » 15.03.2009 22:48:32

Вопрос к знатоками: а как подобное реализовано в VCL (FCL, KOM)?
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Представление Callback функции как метода класса

Сообщение скалогрыз » 15.03.2009 23:11:42

как было сказано выше, для API функций, которые используют callback, обычно разрешается передать UserData (данные которые будут переданы программисту при вызове этой callback функции.

например есть такая API "условная" функция
Код: Выделить всё
TCallbackProc = procedure (SomeData: Integer; UserData:Pointer); stdcall;

procedure SuperPupperAPIFunction( param1, param2: Integer; CallBackProc: TCallbackProc; UserData: Pointer); stdcall; external;

эта в эту функции, передаются входные параметры (param1, param2 - не важно что они значат - чисто условные). При работе этой функции будет вызываться CallBackProc, в который будет передана переменная UserData, та же сама, что и была передана при вызове SuperPupperAPIFunction.

как можно этим воспользоваться.
Код: Выделить всё
type
  TMyObject = class(Tobject)
    procedure Callback(SomeData: Integer);
  end;

// это обработчик
procedure TMyObject.CallBack(SomeData: Integer);
begin
  writeln('SomeData = ', SomeData); 
end;

procedure CallBackProc(SomeData: integer; UserData: Pointer); stdcall;
begin
  // UserData это объект TMyObject, но нужно привести тип!
  TMyObject(UserData).CallBack(SomeData); // передача из функции Callback методу объекта.
end;


...
var
  m : TMyObject;
...
  m := TMyObject.Create; // создали объект, иначе будет плохо!
...
  SuperPupperAPIFunction( x, y, @CallBackProc, m); // в качестве UserData передали объект
...
end.


.хз как яснее написать... яснее будет на живом примере!
это использование типично для различный обёрток :) и не только Delphi/FPC но и C++ и других объектно-оринетрованных языков, где в качестве UserData передаётся объект, и уже CallBack-процедура решает какой метод объекта нужно вызвать.

и ещё. Если писать класс обёртку, то следует "скрывать" (инкапсулировать - о как!) такое использование API, с помощью дополнительного метода объекта:

Код: Выделить всё
interface
...
  TMyObject = class(Tobject)
  protected
    procedure Callback(SomeData: Integer); virtual;
  public
    // обёртка вокруг API функции
    procedure SuperPupper(param1, param2: Integer);
  end;
...

implementation

procedure CallBackProc(SomeData: integer; UserData: Pointer); stdcall;
begin
  // UserData это объект TMyObject, но нужно привести тип!
  TMyObject(UserData).CallBack(SomeData); // передача из функции Callback методу объекта.
end;

// это обработчик
procedure TMyObject.CallBack(SomeData: Integer);
begin
  writeln('SomeData = ', SomeData); 
end;

// этот метод - обёртка для вызова функции SuperPupperAPIFunction
procedure TMyObject.SuperPupper(param1, param2: Integer);
begin
  SuperPupperAPIFunction(param1, param2, @CallBackProc, Self);
end;


отличие этого когда, от перыдущего в том, что использование SuperPupperAPIFunction скрыто, что позволяет добится больше структурированности кода.

и ещё раз: "хз как яснее написать... яснее будет на живом примере"!

ЗЫ: искать хаки, для того чтобы передавать метод объекта, как процедуру - не стоит:
1-х эти решения не будут кроссплатформенными (увы и ах ВСЕГДА придёться лезть в ассемблер и основываться на convention call)
2-х они покажут, что ты программист-индус (в хучшем смысле этого слова).
3-х ненужное усложнение кода.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Представление Callback функции как метода класса

Сообщение Дож » 15.03.2009 23:29:55

Спс большое, пошел писать не индусские живые примеры :)
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47


Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10

Рейтинг@Mail.ru