Оценить:
 Рейтинг: 0

Обратные вызовы в C++

Год написания книги
2021
<< 1 2 3 4 5 6 7 8 ... 13 >>
На страницу:
4 из 13
Настройки чтения
Размер шрифта
Высота строк
Поля

2.1.3. Исполнитель

Реализация исполнителя для случая, когда инициатор разработан в процедурном дизайне, представлена в Листинг 3.

Листинг 3. Исполнитель для инициатора в процедурном дизайне

struct СontextData  // (1)

{

//some context data

};

void callbackHandler(int eventID, void* somePointer)      // (2)

{

//It will be called by initiator

СontextData* pContextData = (СontextData*)somePointer;  // (3)

}

int main()                                 // (4)

{

СontextData clientContext;               // (5)

setup(callbackHandler, &clientContext);  // (6)

run();  // (7)

//Wait finish

}

В строке 1 объявляется тип данных для контекста. Структура здесь показана для примера, в качестве контекста могут выступать любые типы: числа, указатели, смеси и т. п. В строке 2 объявляется функция – обработчик обратного вызова, ее сигнатура должна совпадать с сигнатурой, с которой работает инициатор. Указанная функция будет вызвана инициатором, в нее будут переданы два параметра: первый передается инициатором (информация вызова, в нашем случае это eventID), а второй – это контекст. Клиент должен интерпретировать контекст; нет другого способа это сделать, кроме как приведением типов (строка 3).

Далее, в строке 4 объявлена основная функция, в которой осуществляются все необходимые операции. В строке 5 объявляются данные контекста; в строке 6 производится настройка обратного вызова, в функцию настройки передаются указатель на функцию-обработчик и указатель на контекст; в строке 7 инициатор запускается.

Реализация исполнителя для случая, когда инициатор реализован в объектно-ориентированном дизайне, представлена в Листинг 4. Как видим, она очень похожа на предыдущую реализацию с той разницей, что мы объявляем экземпляр класса-инициатора (строка 5), и все вызовы осуществляем через вызов соответствующих методов класса.

Листинг 4. Исполнитель для инициатора в объектно-ориентированном дизайне

struct СontextData // (1)

{

//some context data

};

void callbackHandler(int eventID, void* somePointer) // (2)

{

//It will be called by initiator

СontextData* pContextData = static_cast<СontextData*>(somePointer); // (3) cast to context

}

int main() // (4)

{

Initiator  initiator;                             // (5)

СontextData clientContext;                        // (6)

initiator.setup(callbackHandler, &clientContext); // (7) callback setup

initiator.run();                                  // (8) initiator has been run

//Wait finish

}

2.1.4. Синхронный вызов

Реализация инициатора для синхронного вызова приведена в Листинг 5. Как видим, для синхронных вызовов код значительно упрощается: нет необходимости хранить переменные, информация вызова и контекст передаются непосредственно в функцию.

Листинг 5. Инициатор для синхронного обратного вызова с указателем на функцию

using ptr_callback  =  void(*) (int, void*);

void run(ptr_callback ptrCallback, void* contextData = NULL)

{

int eventID = 0;

//Some actions

ptrCallback (eventID, contextData);

}
<< 1 2 3 4 5 6 7 8 ... 13 >>
На страницу:
4 из 13