Files
pip/libs/main/system/piplugin.h
2022-12-14 14:13:52 +03:00

245 lines
9.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*! \file piplugin.h
* \ingroup System
* \~\brief
* \~english Plugin control
* \~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 <http://www.gnu.org/licenses/>.
*/
#ifndef PIPLUGIN_H
#define PIPLUGIN_H
#ifndef MICRO_PIP
# include "pilibrary.h"
# include "pistringlist.h"
# ifdef DOXYGEN
//! \~english Declare plugin, should be used before other PIP_PLUGIN_* macros
//! \~russian Объявляет плагин, должен быть использован перед любыми другими PIP_PLUGIN_* макросами
//! \~\relatesalso PIPluginLoader
# define PIP_PLUGIN
//! \~english Set user version to check it while loading, "version" is quoted string
//! \~russian Устанавливает пользовательскую версию для проверки во время загрузки, "version" - строка в кавычках
//! \~\relatesalso PIPluginLoader
# define PIP_PLUGIN_SET_USER_VERSION(version)
//! \~english Add pointer to future merge with plugin. Type is integer
//! \~russian Добавляет указатель для будущего слияния. Тип - целое число
//! \~\relatesalso PIPluginLoader
# define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr)
//! \~english Declare function to merge 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
//! \~english Mark method to export
//! \~russian Пометить метод на экспорт
//! \~\relatesalso PIPluginLoader
# 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
class PIP_EXPORT PIPluginInfo {
public:
PIPluginInfo();
void setUserVersion(const PIString & v);
void setStaticSection(int type, void * ptr);
PIString userVersion() const;
PIMap<int, void *> staticSections() const;
private:
PIString user_version;
PIMap<int, void *> static_sections;
};
class PIP_EXPORT PIPluginInfoStorage {
public:
PIPluginInfoStorage();
PIPluginInfo * currentInfo();
PIPluginInfo * pluginInfo(void * p);
PIPluginInfo * applicationInfo();
PIPluginInfo * enterPlugin(void * p);
void unloadPlugin(void * p);
static PIPluginInfoStorage * instance();
private:
NO_COPY_CLASS(PIPluginInfoStorage);
void * current;
PIMap<void *, PIPluginInfo *> info;
};
//! \ingroup System
//! \~\brief
//! \~english Plugin loader.
//! \~russian Загрузчик плагина.
class PIP_EXPORT PIPluginLoader {
public:
typedef int (*FunctionLoaderVersion)();
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 Load plugin with base filename "name"
//! \~russian Загружает плагин с базовым именем "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
void mergeStatic();
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