Вступление
Кого не посещала, пользуясь open-source библиотеками, мысль: «Спасибо этим парням за эту крутую либу! Когда-нибудь и я напишу что-нибудь стоящее, и выложу это в public, чтоб другие пользовались!»
Да всех! Или не ?..
С приходом стандарта C++17, наши хотелки
решаются гораздо быстрее и изящнее, нужно лишь захотеть воплотить в жизнь задуманную идею, и уметь применять на деле вкусняшки, которыми нас балуют ребята из WG21.
Не слишком ли много и? Хотя: #мыжпрограммисты, для нас это норма )) ...
Предыстория
Тема плагинов довольно интересная, потому что позволяет вносить новый функционал в Программное Обеспечение (ПО) без внесения изменений в ядро программы, но при этом должен быть продуман и написан интерфейс для взаимодействия: ПО <-> Менеджер Плагинов <-> Плагины.
У меня имеется опыт (неудачный) собеседования в фирму, в которой имеется своя плагиновая система для embedded систем, из-за запутанности архитектуры которой я завалил тестовое задание. Там много макросов внутри базовых классов от которых наследуется, и много всякого такого, что делает будни программиста серыми в моменты использования подобных решений...
В один из моментов самообразования, и прочтения статей по C++17 и было принято решение закрепить почерпнутые знания при написании системы плагинов, которая бы была понятной и легкой в использовании.
Насколько плохо или хорошо у меня это получилось — судить вам, дорогие хабровчане...
Обзор
Возможности библиотеки
- Плагины как сервисы (выполняются в отдельных трэдах)
- Автоматическая выгрузка неиспользуемых плагинов
Плюсы
- Простота использования
- Асинхронное выполнение задач
- Header-only дизайн
Минусы
- Если вносится в систему новый плагин, то он должен быть скомпилирован той же версией компилятора что и менеджер его загружающий (также как и libstdc++) для совместимости ABI
- Постоянные кэсты из std::any к используемым типам?
- Проверка фьючерсов на валидность?
Создание плагина
class myplugin : public micro::iplugin {
public:
myplugin(int ver, const std::string& nm):micro::iplugin(ver, nm) {
// регистрация лямбды в плагине
subscribe<2>("sum2",
[](std::any a, std::any b)-> std::any {
return std::any_cast<int>(a) + std::any_cast<int>(b);
},
"справка к функции"
);
}
};
Загрузка плагина
std::shared_ptr<micro::plugins> manager = micro::plugins::get();
std::shared_ptr<micro::iplugin> myplugin = manager->get_plugin("myplugin");
if (myplugin && myplugin->has<2>("sum2")) {
std::shared_future<std::any> result = myplugin->run<2>("sum2", 25, 25);
result.wait();
std::cout << std::any_cast<int>(result.get()) << std::endl;
}
Более детальные примеры смотрите на странице проекта
Вместо заключения
Мне очень приятно читать познавательные статьи на Хабре по С++ (да и не только по C++),
надеюсь и вам эта статья будет интересна и хоть сколько-нибудь познавательна.
По моему скромному мнению, либу можно юзать в проде, пусть взглянут более авторитетные C++'ки и скажут своё слово, исходники хорошо документированы и их не много, — порядка 1000 строк.