245 lines
8.8 KiB
C++
245 lines
8.8 KiB
C++
/*! \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;
|
||
|
||
};
|
||
|
||
|
||
|
||
|
||
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 Нет ошибки */ ,
|
||
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
|