хитрый callback
От: Hard_Club  
Дата: 09.09.10 09:49
Оценка:
Сейчас я пишу небольшой редактор графических форм.

Мне нужно добавлять к элементам формы callbacks, причем что в callback приходит всегда ссылка на объект типа widget (базовая структура данных, которая для разных типов виджетов только обрабатывается по-разному). Мне нужно предоставить пользователю возможность к определенной группе объектов добавлять свои поля данных.

Но загвоздка в том, как в callback определить тип для user data текущего объекта, если во всех widget поле user имеет тип void *, а в один и тот же callback могут приходить разные widget (например, в callback по нажатию мыши)?
Re: хитрый callback
От: artem_korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 09.09.10 10:22
Оценка:
Язык какой?
С уважением, Artem Korneev.
Re: хитрый callback
От: Кодт Россия  
Дата: 09.09.10 10:33
Оценка: +2
Здравствуйте, Hard_Club, Вы писали:

H_C>Мне нужно добавлять к элементам формы callbacks, причем что в callback приходит всегда ссылка на объект типа widget (базовая структура данных, которая для разных типов виджетов только обрабатывается по-разному). Мне нужно предоставить пользователю возможность к определенной группе объектов добавлять свои поля данных.


H_C>Но загвоздка в том, как в callback определить тип для user data текущего объекта, если во всех widget поле user имеет тип void *, а в один и тот же callback могут приходить разные widget (например, в callback по нажатию мыши)?


То есть,
— с одной стороны, у колбека должна быть какая-то связанная переменная, определяемая пользователем (например, адрес объекта-приёмника)
— с другой стороны, этот колбек должен принимать полиморфные данные

Есть несколько решений.

Первое — в духе ООП.
Определяем интерфейс ICallback, у которого есть все нужные сигнатуры
struct ICallback
{
  virtual void on_mouse(Point where, int buttons, int flags) = 0;
  virtual void on_keyboard(int keycode, char letter, int shifts, int flags, int repeat) = 0;
  virtual void on_timer(int identifier) = 0;
  .....
};

Тогда связанной переменной является собственно адрес объекта, реализующего этот интерфейс.

Второе — в духе Plain Old C.
Полиморфные данные — это вариантный тип.
Колбек — это пара (указатель на функцию, указатель на что угодно).
typedef struct tagEvent
{
  int type;
  union
  {
    MouseEvent mouse;
    KeyboardEvent keyboard;
    TimerEvent timer;
    ....
  } details;
} Event;

typedef void (*callback_func)(void* param, Event* event);

typedef struct tagCallback
{
  callback_func func;
  void* param;
} Callback;

Сделать красивую С++ную обёртку для сишной — не составит труда.

Развитием идеи являются boost::function + boost::variant / boost::any
typedef variant<MouseEvent, KeyboardEvent, TimerEvent> Event;
typedef function<void(Event*)> Callback;


И, наконец, boost::signal.
В нём есть не только механизм вызова, но и механизм подписки и рассылки.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.