//! \~\ingroup System //! \~\file piplugin.h //! \~\brief //! \~english Plugin control //! \~russian Управление плагинами //! \~\details //! \~english Plugin helpers for dynamic library loading and plugin management //! \~russian Вспомогательные средства для загрузки динамических библиотек и управления плагинами /* PIP - Platform Independent Primitives Plugin helpers Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIPLUGIN_H #define PIPLUGIN_H #ifndef MICRO_PIP # include "pilibrary.h" # include "pistringlist.h" # ifdef DOXYGEN //! \relatesalso PIPluginLoader //! \~\brief //! \~english Declares plugin entry points and should be used before other \c PIP_PLUGIN_* macros. //! \~russian Объявляет точки входа плагина и должен использоваться перед другими макросами \c PIP_PLUGIN_*. # define PIP_PLUGIN //! \relatesalso PIPluginLoader //! \~\brief //! \~english Sets user version checked during loading, "version" is quoted string. //! \~russian Устанавливает строковую пользовательскую версию, проверяемую при загрузке, "version" - строка в кавычках. # define PIP_PLUGIN_SET_USER_VERSION(version) //! \relatesalso PIPluginLoader //! \~\brief //! \~english Registers a static section pointer for future merge. \a type is an integer key. //! \~russian Регистрирует указатель на статическую секцию для последующего слияния. \a type - целочисленный ключ. # define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) //! \relatesalso PIPluginLoader //! \~\brief //! \~english Declares a function that merges plugin and application static sections. //! \~russian Объявляет функцию для слияния статических секций плагина и приложения. //! \~\details //! \~english //! This is functions with 3 arguments: (int type, void * from, void * to). //! This function invoked first while loading plugin with //! "from" - plugin scope, "to" - application scope, and second //! (optionally) on \a PIPluginLoader::mergeStatic() method with //! "from" - application scope, "to" - plugin scope. So with macro //! you can merge application and plugin static data. //! \~russian //! Этот метод имеет 3 аргумента: (int type, void * from, void * to). //! Он вызывается первый раз при загрузке плагина с "from" - областью плагина, //! "to" - областью приложения, и второй раз (необязательно) при вызове //! \a PIPluginLoader::mergeStatic() с "from" - областью приложения и //! "to" - областью плагина. Таким образом, этот макрос позволяет провести //! слияние статических данных приложения и плагина. //! \~\relatesalso PIPluginLoader # define PIP_PLUGIN_STATIC_SECTION_MERGE //! \relatesalso PIPluginLoader //! \~\brief //! \~english Marks a plugin function for export. //! \~russian Помечает функцию плагина для экспорта. # define PIP_PLUGIN_EXPORT # else # ifdef WINDOWS # define PIP_PLUGIN_EXPORT __declspec(dllexport) # else # define PIP_PLUGIN_EXPORT # endif # define __PIP_PLUGIN_LOADER_VERSION_FUNC__ pip_loader_version # define __PIP_PLUGIN_STATIC_MERGE_FUNC__ pip_merge_static # define __PIP_PLUGIN_LOADER_VERSION__ 2 # define PIP_PLUGIN_SET_USER_VERSION(v) \ STATIC_INITIALIZER_BEGIN \ PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \ if (pi) pi->setUserVersion(v); \ STATIC_INITIALIZER_END # define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) \ STATIC_INITIALIZER_BEGIN \ PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \ if (pi) pi->setStaticSection(type, ptr); \ STATIC_INITIALIZER_END # define PIP_PLUGIN \ extern "C" { \ PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() { \ return __PIP_PLUGIN_LOADER_VERSION__; \ } \ } # define PIP_PLUGIN_STATIC_SECTION_MERGE \ extern "C" { \ PIP_PLUGIN_EXPORT void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to); \ } \ void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to) # endif //! \~\ingroup System //! \~\brief //! \~english Metadata collected for one plugin or for the host application. //! \~russian Метаданные, собираемые для одного плагина или для основного приложения. class PIP_EXPORT PIPluginInfo { public: //! \~english Constructs empty plugin metadata. //! \~russian Создает пустые метаданные плагина. PIPluginInfo(); //! \~english Sets user version checked by \a PIPluginLoader::load(). //! \~russian Устанавливает пользовательскую версию, проверяемую в \a PIPluginLoader::load(). void setUserVersion(const PIString & v); //! \~english Associates a static section pointer with integer \a type. //! \~russian Связывает указатель на статическую секцию с целочисленным типом \a type. void setStaticSection(int type, void * ptr); //! \~english Returns configured user version string. //! \~russian Возвращает установленную строку пользовательской версии. PIString userVersion() const; //! \~english Returns registered static section pointers. //! \~russian Возвращает зарегистрированные указатели статических секций. PIMap staticSections() const; private: PIString user_version; PIMap static_sections; }; //! \~\ingroup System //! \~\brief //! \~english Storage of plugin metadata for the application and loaded plugins. //! \~russian Хранилище метаданных плагинов для приложения и загруженных плагинов. class PIP_EXPORT PIPluginInfoStorage { public: //! \~english Creates storage and initializes application metadata entry. //! \~russian Создает хранилище и инициализирует запись метаданных приложения. PIPluginInfoStorage(); //! \~english Returns metadata of the current initialization scope. //! \~russian Возвращает метаданные текущей области инициализации. PIPluginInfo * currentInfo(); //! \~english Returns metadata associated with plugin pointer \a p. //! \~russian Возвращает метаданные, связанные с указателем плагина \a p. PIPluginInfo * pluginInfo(void * p); //! \~english Returns metadata entry of the host application. //! \~russian Возвращает запись метаданных основного приложения. PIPluginInfo * applicationInfo(); //! \~english Enters plugin scope \a p and creates metadata entry if needed. //! \~russian Переходит в область плагина \a p и при необходимости создает запись метаданных. PIPluginInfo * enterPlugin(void * p); //! \~english Removes metadata associated with plugin pointer \a p. //! \~russian Удаляет метаданные, связанные с указателем плагина \a p. void unloadPlugin(void * p); //! \~english Returns process-wide singleton storage. //! \~russian Возвращает глобальный синглтон хранилища. static PIPluginInfoStorage * instance(); private: NO_COPY_CLASS(PIPluginInfoStorage); void * current; PIMap info; }; //! \~\ingroup System //! \~\brief //! \~english Plugin loader. //! \~russian Загрузчик плагина. //! \details //! \~english Handles dynamic library loading, symbol resolution, and plugin lifecycle management //! \~russian Управляет загрузкой динамических библиотек, разрешением символов и жизненным циклом плагинов class PIP_EXPORT PIPluginLoader { public: //! \~english Signature of the exported loader version function. //! \~russian Сигнатура экспортируемой функции версии загрузчика. typedef int (*FunctionLoaderVersion)(); //! \~english Signature of the exported static merge function. //! \~russian Сигнатура экспортируемой функции слияния статических секций. typedef void (*FunctionStaticMerge)(int, void *, void *); //! \~english Possible load plugin error //! \~russian Возможные ошибки загрузки плагина enum Error { Unknown /** \~english No \a load() call yet \~russian Не было вызова \a load() */, NoError /** \~english No error \~russian Нет ошибки */, NoSuchFile /** \~english Can`t find library file \~russian Не найден файл библиотеки */, LibraryLoadError /** \~english System can`t load library \~russian Система не смогла загрузить библиотеку */, MissingSymbols /** \~english Can`t find necessary symbols \~russian Нет необходимых методов */, InvalidLoaderVersion /** \~english Internal version mismatch \~russian Неверная внутренняя версия */, InvalidUserVersion /** \~english User version mismatch \~russian Неверная пользовательская версия */, }; //! \~english Contruct loader with base filename "name" and call \a load() if "name" not empty //! \~russian Создает загрузчик с базовым именем файла "name" и вызывает \a load() если "name" не пустое PIPluginLoader(const PIString & name = PIString()); //! \~english Destructor, unload library //! \~russian Деструктор, выгружает библиотеку ~PIPluginLoader(); //! \~english Loads plugin by base filename \a name and updates error state on failure. //! \~russian Загружает плагин по базовому имени файла \a name и обновляет состояние ошибки при неудаче. bool load(const PIString & name); //! \~english Unload plugin and free library //! \~russian Выгружает плагин и освобождает библиотеку void unload(); //! \~english Returns if plugin is successfully loaded //! \~russian Возвращает успешно ли загружен плагин bool isLoaded() const; //! \~english Returns error of last \a load() call //! \~russian Возвращает ошибку последнего вызова \a load() Error lastError() const; //! \~english Returns error message of last \a load() call //! \~russian Возвращает сообщение об ошибке последнего вызова \a load() PIString lastErrorText() const; //! \~english Set if %PIPluginLoader should print load messages, \b true by default //! \~russian Устанавливает должен ли %PIPluginLoader выводить сообщения, \b true по умолчанию void setMessages(bool yes); //! \~english Returns if %PIPluginLoader should print load messages, \b true by default //! \~russian Возвращает должен ли %PIPluginLoader выводить сообщения, \b true по умолчанию bool isMessages() const; //! \~english Returns loaded plugin library path //! \~russian Возвращает путь к загруженной библиотеке PIString libPath(); //! \~english Obtain exported library method with name "symbol" //! \~russian Получает экспортированный метод библиотеки с именем "symbol" //! \~\sa PILibrary::resolve() void * resolve(const char * name); //! \~english Invoke plugin \a PIP_PLUGIN_STATIC_SECTION_MERGE //! \~russian Вызывает у плагина \a PIP_PLUGIN_STATIC_SECTION_MERGE //! \details //! \~english Calls the plugin's static section merge function to synchronize application and plugin data //! \~russian Вызывает функцию слияния статических секций плагина для синхронизации данных приложения и плагина void mergeStatic(); //! \~english Returns existing plugin directories for subdirectory \a name. //! \~russian Возвращает существующие каталоги плагинов для подкаталога \a name. static PIStringList pluginsDirectories(const PIString & name); private: NO_COPY_CLASS(PIPluginLoader); PIString findLibrary(const PIString & path); static PIString libExtension(); PILibrary lib; FunctionLoaderVersion func_loader_version; FunctionStaticMerge func_static_merge; PIString error_str; Error error; bool loaded, messages; }; #endif // MICRO_PIP #endif // PIPLUGIN_H