This commit is contained in:
2022-04-23 00:44:52 +03:00
parent 8da0469dbf
commit 7a458c5cbe
3 changed files with 204 additions and 61 deletions

View File

@@ -32,13 +32,24 @@
//! \~english Plugin loader
//! \~russian Загрузчик плагина
//!
//! \section PIPluginLoader_sec0 Synopsis
//! This class provides several macro to define plugin and %PIPluginLoader - class
//! \~\details
//! \~english \section PIPluginLoader_sec0 Synopsis
//! \~russian \section PIPluginLoader_sec0 Краткий обзор
//!
//! \~english
//! This file provides several macro to define plugin and %PIPluginLoader - class
//! to load and check plugin.
//!
//! \section PIPluginLoader_sec1 Plugin side
//! \~russian
//! Этот файл предоставляет несколько макросов для объявления плагина и
//! %PIPluginLoader - класс для его загрузки и проверки.
//!
//!
//! \~english \section PIPluginLoader_sec1 Plugin side
//! \~russian \section PIPluginLoader_sec1 Сторона плагина
//! \~english
//! Plugin is a shared library that can be loaded in run-time.
//! This is only PIP_PLUGIN macro necessary to define plugin.
//! This is only \a PIP_PLUGIN macro necessary to define plugin.
//! If you want to set and check some version, use macro
//! \a PIP_PLUGIN_SET_USER_VERSION(version). Also you can
//! define a function to merge static sections between application
@@ -46,38 +57,84 @@
//! merge, you should set pointers to that sections with macro
//! \a PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr).
//!
//! \section PIPluginLoader_sec2 Application side
//! \~russian
//! Плагин - это разделяемая библиотека, которая может быть
//! загружена динамически. Необходимым является только макрос \a PIP_PLUGIN.
//! Можно установить версию для дополнительной проверки с помощью
//! макроса \a PIP_PLUGIN_SET_USER_VERSION(version). Также
//! можно объявить метод для слияния статических секций между
//! приложением и плагином с помощью макроса \a PIP_PLUGIN_STATIC_SECTION_MERGE.
//! Перед слиянием необходимо установить указатели для секций с
//! помощью макроса \a PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr).
//!
//!
//! \~english \section PIPluginLoader_sec2 Application side
//! \~russian \section PIPluginLoader_sec2 Сторона приложения
//! \~english
//! Application should use class \a PIPluginLoader to load
//! plugin. Main function is \a load(PIString name).
//! "name" is base name of library, %PIPluginLoader
//! try to use sevaral names, \<name\>, lib\<name\> and
//! "dll", "so" and "dylib" extensions, depends on system.
//! "dll", "so" and "dylib" extensions, depends on system.\n
//! For example:
//! \code
//!
//! \~russian
//! Приложение должно использовать класс \a PIPluginLoader
//! для загрузки плагина. Основной метод - это \a load(PIString name).
//! "name" является базовым именем для поиска библиотеки.
//! %PIPluginLoader попробует несколько имен, \<name\>, lib\<name\> и
//! расширения "dll", "so" и "dylib", в зависимости от системы.\n
//! Например:
//!
//! \~\code
//! PIPluginLoader l;
//! l.load("foo");
//! \endcode
//!
//! \~english
//! On Windows, try to open "foo", "libfoo", "foo.dll" and
//! "libfoo.dll".
//! "libfoo.dll".\n
//! If you using user version check, you should set it
//! with macro \a PIP_PLUGIN_SET_USER_VERSION(version).
//! When plugin is successfully loaded and checked,
//! you can load your custom symbols with function
//! \a resolve(name), similar to PILibrary.
//! \note You should use PIP_PLUGIN_EXPORT and "export "C""
//! \note You should use \a PIP_PLUGIN_EXPORT and [C-linkage](https://en.cppreference.com/w/cpp/language/language_linkage)
//! with functions you want to use with \a resolve(name)!
//!
//! \section PIPluginLoader_sec3 Static sections
//! \~russian
//! На Windows будут опробованы "foo", "libfoo", "foo.dll" и
//! "libfoo.dll".\n
//! Если нужна проверка пользовательской версии, установите
//! ей с помощью макроса \a PIP_PLUGIN_SET_USER_VERSION(version).
//! Когда плагин будет успешно загружен и проверен, можно будет
//! получать из него свои методы с помощью \a resolve(name),
//! аналогично PILibrary.
//! \note Необходимо использовать \a PIP_PLUGIN_EXPORT и [C-linkage](https://en.cppreference.com/w/cpp/language/language_linkage)
//! для методов, получаемых через \a resolve(name)!
//!
//!
//! \~english \section PIPluginLoader_sec3 Static sections
//! \~russian \section PIPluginLoader_sec3 Статические секции
//! \~english
//! Macro \a PIP_PLUGIN_STATIC_SECTION_MERGE defines function
//! with arguments (int type, void * from, void * to), so you
//! can leave this macro as declaration or define its body next:
//! \code
//!
//! \~russian
//! Макрос \a PIP_PLUGIN_STATIC_SECTION_MERGE объявляет метод
//! с аргументами (int type, void * from, void * to), поэтому
//! можно оставить его как объявление, или реализовать тут же:
//!
//! \~\code
//! PIP_PLUGIN_STATIC_SECTION_MERGE() {
//! switch (type) {
//! ...
//! }
//! }
//! \endcode
//!
//! \~english
//! \note If you using singletones, remember that cpp-defined
//! singletones in shared libraries are single for whole application,
//! including plugins! But if you use h-defined singletones or
@@ -87,14 +144,31 @@
//! Anyway, if this is macro \a PIP_PLUGIN_STATIC_SECTION_MERGE, it
//! called once while loading plugin with "from" - plugin side
//! and "to" - application side, and second (optionally) on method
//! \a mergeStatic() with "from" - application side and "to" - plugin side.
//! \a mergeStatic() with "from" - application side and "to" - plugin side.\n
//! First direction allow you to copy all defined static content from plugin
//! to application, and second - after loading all plugins (for example)
//! to copy static content from application (and all plugins) to plugin.
//! to copy static content from application (and all other plugins) to plugin.
//!
//! \section PIPluginLoader_sec4 Examples
//! Simple plugin:
//! \code
//! \~russian
//! \note При использовании синглтонов надо помнить, что реализованные
//! в cpp синглтоны в разделяемых библиотеках едины для всего приложения,
//! включая плагины! Однако реализованные в h-файлах синглтоны, либо
//! из статических библиотек, не являются реальными одиночками,
//! и для каждого плагина и приложения будет свой объект. В этом случае
//! можно провести слияние статических секций.
//!
//! В любом случае, если используется макрос \a PIP_PLUGIN_STATIC_SECTION_MERGE,
//! то он вызывается первый раз во время загрузки плагина с "from" - областью плагина,
//! "to" - областью приложения, и второй раз (необязательно) при вызове
//! \a mergeStatic() с "from" - областью приложения и "to" - областью плагина.\n
//! Первый вызов позволяет скопировать статические секции из плагина в приложение,
//! второй - из приложения (и всех остальных плагинов) в плагин.
//!
//! \~english \section PIPluginLoader_sec4 Examples
//! \~russian \section PIPluginLoader_sec4 Примеры
//! \~english Simple plugin:
//! \~russian Простой плагин:
//! \~\code
//! #include <piplugin.h>
//!
//! PIP_PLUGIN
@@ -106,8 +180,9 @@
//! }
//! \endcode
//!
//! Application:
//! \code
//! \~english Application:
//! \~russian Приложение:
//! \~\code
//! #include <piplugin.h>
//! int main() {
//! PIPluginLoader pl;
@@ -121,8 +196,9 @@
//! }
//! \endcode
//!
//! Complex plugin:
//! \code
//! \~english Complex plugin:
//! \~russian Сложный плагин:
//! \~\code
//! #include <piplugin.h>
//!
//! PIStringList global_list;
@@ -142,8 +218,9 @@
//! }
//! \endcode
//!
//! Application:
//! \code
//! \~english Application:
//! \~russian Приложение:
//! \~\code
//! #include <piplugin.h>
//!
//! PIStringList global_list;
@@ -254,6 +331,13 @@ PIPluginLoader::~PIPluginLoader() {
}
//! \~\details
//! \~english
//! Loader try prefix "lib" and suffix ".dll",
//! ".so" or ".dylib", depends on platform.
//! \~russian
//! Загрузчик пробует приставку "lib" и окончания
//! ".dll", ".so" или ".dylib", в зависимости от системы
bool PIPluginLoader::load(const PIString & name) {
unload();
PIPluginInfo * ai = PIPluginInfoStorage::instance()->applicationInfo();
@@ -356,6 +440,13 @@ void * PIPluginLoader::resolve(const char * name) {
}
//! \~\details
//! \~english
//! Call PIP_PLUGIN_STATIC_SECTION_MERGE function
//! on every common type, with "from" - application scope,
//! "to" - plugin scope
//! \~russian
//!
void PIPluginLoader::mergeStatic() {
if (!loaded || !func_static_merge) return;
PIPluginInfo * ai = PIPluginInfoStorage::instance()->applicationInfo();