Используйте неклассный член в качестве обработчика события

Я пишу оболочку DLL для класса C++Builder VCL. Это чрезвычайно упрощенный пример проблемы:

typedef void __fastcall (__closure *TMyEvent)(int index);

class TMyClass {
  public:
    TMyEvent OnMyEvent;
};

void __fastcall myEventHandler(int index) { }

TMyClass myClass;
myClass.OnMyEvent = myEventHandler;

... и вот проблема:

Обычно myEventHandler определяется внутри другого класса, но здесь он определяется как глобальная функция. Когда я пытаюсь назначить myEventHandler в myClass.OnMyEvent Я получаю ошибку

Невозможно преобразовать void(int) в TMyEvent

Я повторно использую TMyClass генерировать различные виды оберток и нуждаются в __closeure в typedef так что это хорошо работает с проектами VCL формы.

Это __closure эта проблема? Можно ли вообще использовать глобальную функцию в качестве обработчика событий?

1 ответ

Решение

__closure Расширение компилятора - это специальный тип указателя на метод класса, который содержит два указателя - указатель на экземпляр объекта и указатель на метод-обработчик. Когда __closure выполняется, компилятор передает указатель объекта в обработчик через его this параметр. Таким образом, обработчик ДОЛЖЕН иметь this параметр.

Если обработчик является нестатическим членом класса, this Указатель обрабатывается неявно компилятором для вас, например:

class TMyEvents {
public:
    void __fastcall myEventHandler(int index) { }
};

TMyClass myClass;
TMyEvents myEvents;
myClass.OnMyEvent = myEvents.myEventHandler;

Если обработчик является автономной функцией или статическим методом класса, тогда this указатель должен быть явно указан в списке параметров. В этой ситуации вы можете использовать TMethod 1 структура, чтобы помочь вам назначить обработчик для события, например:

void __fastcall myEventHandler(void *Data, int index) { }

TMethod m;
m.Data = ...; // can be anything you want to pass to the 'Data' parameter
m.Code = &myEventHandler;

TMyClass myClass;
myClass.OnMyEvent = reinterpret_cast<TMyEvent&>(m);

1: это работает только с __closure! Не пытайтесь использовать его с другими типами указателей на функции.

Другие вопросы по тегам