diff --git a/libs/main/system/piplugin.cpp b/libs/main/system/piplugin.cpp index 5db97ffb..45701453 100644 --- a/libs/main/system/piplugin.cpp +++ b/libs/main/system/piplugin.cpp @@ -162,37 +162,70 @@ PIPluginInfo::PIPluginInfo() { - in_plugin = false; } void PIPluginInfo::setUserVersion(const PIString & v) { - user_version[in_plugin ? 1 : 0] = v; + user_version = v; } void PIPluginInfo::setStaticSection(int type, void * ptr) { - static_sections[in_plugin ? 1 : 0][type] = ptr; + static_sections[type] = ptr; } -PIString PIPluginInfo::userVersion(bool plugin) const { - return user_version[plugin ? 1 : 0]; +PIString PIPluginInfo::userVersion() const { + return user_version; } -PIMap PIPluginInfo::staticSections(bool plugin) const { - return static_sections[plugin ? 1 : 0]; +PIMap PIPluginInfo::staticSections() const { + return static_sections; } -void PIPluginInfo::enterPlugin() { - in_plugin = true; + + + +PIPluginInfoStorage::PIPluginInfoStorage() { + enterPlugin(0); } -PIPluginInfo * PIPluginInfo::instance() { - static PIPluginInfo ret; +PIPluginInfo * PIPluginInfoStorage::currentInfo() { + return info[current]; +} + + +PIPluginInfo * PIPluginInfoStorage::pluginInfo(void * p) { + return info.value(p, nullptr); +} + + +PIPluginInfo * PIPluginInfoStorage::applicationInfo() { + return info[0]; +} + + +PIPluginInfo * PIPluginInfoStorage::enterPlugin(void * p) { + current = p; + PIPluginInfo *& i(info[p]); + if (!i) i = new PIPluginInfo(); + return i; +} + + +void PIPluginInfoStorage::unloadPlugin(void * p) { + if (current == p) current = 0; + PIPluginInfo *& i(info[p]); + if (!i) delete i; + info.remove(p); +} + + +PIPluginInfoStorage * PIPluginInfoStorage::instance() { + static PIPluginInfoStorage ret; return &ret; } @@ -201,61 +234,61 @@ PIPluginInfo * PIPluginInfo::instance() { PIPluginLoader::PIPluginLoader(const PIString & name) { func_loader_version = nullptr; - func_plugin_info = nullptr; func_static_merge = nullptr; - plugin_info = nullptr; + error = Unknown; loaded = false; + messages = true; if (!name.isEmpty()) load(name); } PIPluginLoader::~PIPluginLoader() { - lib.unload(); + unload(); } bool PIPluginLoader::load(const PIString & name) { unload(); + PIPluginInfo * ai = PIPluginInfoStorage::instance()->applicationInfo(); + PIPluginInfo * pi = PIPluginInfoStorage::instance()->enterPlugin(this); if (!lib.load(findLibrary(name))) { - piCout << "Load plugin \"" << name << "\"load failed with error: " << lib.lastError().trimmed(); + unload(); + error = LibraryLoadError; + error_str = "Load plugin \"" + name + "\" error: can`t load lib: " + lib.lastError(); + if (messages) piCout << error_str; return false; } //piCout << "loading" << lib.path() << "..."; func_loader_version = (FunctionLoaderVersion)lib.resolve(STR(__PIP_PLUGIN_LOADER_VERSION_FUNC__)); if (!func_loader_version) { - piCout << "Load plugin \"" << name << "\" error: can`t find" << STR(__PIP_PLUGIN_LOADER_VERSION_FUNC__); unload(); + error = MissingSymbols; + error_str = "Load plugin \"" + name + "\" error: can`t find " + STR(__PIP_PLUGIN_LOADER_VERSION_FUNC__); + if (messages) piCout << error_str; return false; } if (__PIP_PLUGIN_LOADER_VERSION__ != func_loader_version()) { - piCout << "Load plugin \"" << name << "\" error: invalid loader version: plugin" << __PIP_PLUGIN_LOADER_VERSION__ << "!=" << func_loader_version(); unload(); + error = InvalidLoaderVersion; + error_str = "Load plugin \"" + name + "\" error: invalid loader version: application = " + PIString::fromNumber(func_loader_version()) + + ", plugin = " + PIString::fromNumber(__PIP_PLUGIN_LOADER_VERSION__); + if (messages) piCout << error_str; return false; } - func_plugin_info = (FunctionPluginInfo)lib.resolve(STR(__PIP_PLUGIN_PLUGIN_INFO_FUNC__)); - if (!func_plugin_info) { - piCout << "Load plugin \"" << name << "\" error: can`t find" << STR(__PIP_PLUGIN_PLUGIN_INFO_FUNC__); - unload(); - return false; - } - plugin_info = func_plugin_info(); - if (!plugin_info) { - piCout << "Load plugin \"" << name << "\" error: null PIPluginInfo"; - unload(); - return false; - } - if (PIPluginInfo::instance()->userVersion(false).size_s() > 1) { - PIString pversion = plugin_info->userVersion(true), lversion = PIPluginInfo::instance()->userVersion(false); + if (ai->userVersion().size_s() > 1) { + PIString pversion = pi->userVersion(), lversion = ai->userVersion(); if (pversion != lversion) { - piCout << "Load plugin \"" << name << "\" error: invalid user version: plugin" << pversion << "!=" << lversion; unload(); + error = InvalidUserVersion; + error_str = "Load plugin \"" + name + "\" error: invalid user version: application = " + lversion + ", plugin = " + pversion; + if (messages) piCout << error_str; return false; } } func_static_merge = (FunctionStaticMerge)lib.resolve(STR(__PIP_PLUGIN_STATIC_MERGE_FUNC__)); if (func_static_merge) { - auto pss = plugin_info->staticSections(true), lss = PIPluginInfo::instance()->staticSections(false); + auto pss = pi->staticSections(), lss = ai->staticSections(); //piCout << lss.keys() << pss.keys(); auto it = lss.makeIterator(); while (it.next()) { @@ -267,14 +300,17 @@ bool PIPluginLoader::load(const PIString & name) { } } loaded = true; + error = NoError; return true; } void PIPluginLoader::unload() { lib.unload(); - plugin_info = nullptr; loaded = false; + error_str.clear(); + error = Unknown; + PIPluginInfoStorage::instance()->unloadPlugin(this); } @@ -283,13 +319,28 @@ bool PIPluginLoader::isLoaded() const { } -PIString PIPluginLoader::libPath() { - return lib.path(); +PIPluginLoader::Error PIPluginLoader::lastError() const { + return error; } -PIString PIPluginLoader::lastError() { - return lib.lastError(); +PIString PIPluginLoader::lastErrorText() const { + return error_str; +} + + +void PIPluginLoader::setMessages(bool yes) { + messages = yes; +} + + +bool PIPluginLoader::isMessages() const { + return messages; +} + + +PIString PIPluginLoader::libPath() { + return lib.path(); } @@ -300,8 +351,10 @@ void * PIPluginLoader::resolve(const char * name) { void PIPluginLoader::mergeStatic() { - if (!loaded || !func_static_merge || !plugin_info) return; - auto pss = plugin_info->staticSections(true), lss = PIPluginInfo::instance()->staticSections(false); + if (!loaded || !func_static_merge) return; + PIPluginInfo * ai = PIPluginInfoStorage::instance()->applicationInfo(); + PIPluginInfo * pi = PIPluginInfoStorage::instance()->pluginInfo(this); + auto pss = pi->staticSections(), lss = ai->staticSections(); auto it = lss.makeIterator(); while (it.next()) { if (!pss.contains(it.key())) diff --git a/libs/main/system/piplugin.h b/libs/main/system/piplugin.h index 1238235f..9e75c534 100644 --- a/libs/main/system/piplugin.h +++ b/libs/main/system/piplugin.h @@ -68,27 +68,24 @@ #endif #define __PIP_PLUGIN_LOADER_VERSION_FUNC__ pip_loader_version -#define __PIP_PLUGIN_PLUGIN_INFO_FUNC__ pip_plugin_info #define __PIP_PLUGIN_STATIC_MERGE_FUNC__ pip_merge_static -#define __PIP_PLUGIN_LOADER_VERSION__ 1 +#define __PIP_PLUGIN_LOADER_VERSION__ 2 #define PIP_PLUGIN_SET_USER_VERSION(v) \ STATIC_INITIALIZER_BEGIN \ - PIPluginInfo::instance()->setUserVersion(v); \ + 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::instance()->setStaticSection(type, ptr); \ + PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \ + if (pi) pi->setStaticSection(type, ptr); \ STATIC_INITIALIZER_END #define PIP_PLUGIN \ - STATIC_INITIALIZER_BEGIN \ - PIPluginInfo::instance()->enterPlugin(); \ - STATIC_INITIALIZER_END \ extern "C" { \ PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() {return __PIP_PLUGIN_LOADER_VERSION__;} \ - PIP_PLUGIN_EXPORT PIPluginInfo * __PIP_PLUGIN_PLUGIN_INFO_FUNC__() {return PIPluginInfo::instance();} \ } #define PIP_PLUGIN_STATIC_SECTION_MERGE \ @@ -108,16 +105,34 @@ public: void setUserVersion(const PIString & v); void setStaticSection(int type, void * ptr); - PIString userVersion(bool plugin) const; - PIMap staticSections(bool plugin) const; - void enterPlugin(); - - static PIPluginInfo * instance(); + PIString userVersion() const; + PIMap staticSections() const; private: - PIString user_version[2]; - PIMap static_sections[2]; - bool in_plugin; + PIString user_version; + PIMap 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 info; }; @@ -127,9 +142,18 @@ private: class PIP_EXPORT PIPluginLoader { public: typedef int(*FunctionLoaderVersion)(); - typedef PIPluginInfo*(*FunctionPluginInfo)(); typedef void(*FunctionStaticMerge)(int, void *, void *); + //! Possible load plugin error + enum Error { + Unknown /** No \a load call yet */ , + NoError /** No error */ , + LibraryLoadError /** System can`t load library */ , + MissingSymbols /** Can`t find necessary symbols */ , + InvalidLoaderVersion /** Integer version mismatch */ , + InvalidUserVersion /** User version mismatch */ , + }; + //! Contruscts loader with filename "name" PIPluginLoader(const PIString & name = PIString()); @@ -147,12 +171,21 @@ public: //! Returns if plugin is successfully loaded bool isLoaded() const; + //! Returns error of last \a load() call + Error lastError() const; + + //! Returns error message of last \a load() call + PIString lastErrorText() const; + + //! Set if %PIPluginLoader should print load messages, \b true by default + void setMessages(bool yes); + + //! Returns if %PIPluginLoader should print load messages, \b true by default + bool isMessages() const; + //! Returns loaded plugin library path PIString libPath(); - //! Returns library lastError - PIString lastError(); - //! Resolve symbol "name" from plugin library void * resolve(const char * name); @@ -169,10 +202,10 @@ private: PILibrary lib; FunctionLoaderVersion func_loader_version; - FunctionPluginInfo func_plugin_info; FunctionStaticMerge func_static_merge; - PIPluginInfo * plugin_info; - bool loaded; + PIString error_str; + Error error; + bool loaded, messages; };