c++ библиотека с событиями
Озадачился я на неделе в написании библиотеки для своих проектов.
Пока что для виртуального последовательного порта.
Суть такая: код библиотеки выполняется периодически (некий интервал) и опрашивает порт. При получении данных он их парсит и как положено раскидывает.
Ну так вот, есть такие комбинации команд от устройства, когда надо, чтобы основной программе тюкнуло, мол, вот те разбитые данные, выводи в лог.
Т.е. нужен некий event, чтобы в основной программе его прикрутить наподобии событий в проектах для форточек кнопочкам при нажатии:
buttonName_click (некие_входные_данные) {
некий_код;
}
Т.е. чтобы при поступлении события от библиотеки моя программа подрывалась выполнять вложенный код:
myLib_event() {
код_если_произошло_событие_в_библиотеке;
}
Как подобное можно реализовать?
Вариант копипастить от проекта к проекту не подходит:
- Проектов несколько, банально в версиях запутаюсь (куда копирнул, что, а куда ещё нет);
- Запарно (постоянно копипастить код и следить за версиями);
- Формат пакета девайса может измениться, что потребует изменения кода везде... За тем библиотеки и пишут, чтобы по 100500 раз не развозить всяких копий. С библиотекой достаточно просто рекомпильнуть новую версию софтины;
- Может изменится логика, когда надо выводить, а когда нет;
- Проще новый проект накидать, или изменить существующий. Ядро трогать нет нужды, только вывод.
Дополнительно: Как расшаривать пространство под данные девайса. Т.е. создавать общее некое пространство (массив), чтобы библиотека туды кидала готовые данные и пинала прогу, что есть событие... А та могла достать эти данные и уже по-своему их вывести-перенести-обработать-сохранить и всякое...
Ответы (1 шт):
Попробую кратко описать возможные варианты:
1.Это Си подход, когда в библиотеку передаем указатель на функцию обработчик
#include <iostream>
typedef void (*FunctionPtr)(int);
class MyLibClass
{
public:
void addListener(FunctionPtr _func)
{
m_func = _func;
}
void someLibEventLoop()
{
//..
for(int i = 0 ; i < 5 ; i++)
{
if(m_func)
{
m_func(i);
}
}
}
FunctionPtr m_func = nullptr;
};
void clientFunction(int _v)
{
std::cout << __FUNCTION__ << " | " << _v << std::endl;
}
int main(int argc, char *argv[])
{
MyLibClass libClass;
libClass.addListener(clientFunction);
libClass.someLibEventLoop();
return 0;
}
2.Более продвинутый вариант - использовать std::function, тогда для подписки можно использовать лямбды
#include <iostream>
#include <functional>
class MyLibClass
{
public:
void addListener(std::function<void(int)> _func)
{
m_func = _func;
}
void someLibEventLoop()
{
//..
for(int i = 0 ; i < 5 ; i++)
{
if(m_func)
{
m_func(i);
}
}
}
std::function<void(int)> m_func = nullptr;
};
int main(int argc, char *argv[])
{
MyLibClass libClass;
libClass.addListener([](int _v)
{
std::cout << __FUNCTION__ << " | " << _v << std::endl;
});
libClass.someLibEventLoop();
return 0;
}
3.4. Использовать готовые системы, типа сигналы слоты из Qt или Boost Signals