/*! \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 . */ #ifndef PIPLUGIN_H #define PIPLUGIN_H #ifndef MICRO_PIP #include "pilibrary.h" #include "pistringlist.h" #ifdef DOXYGEN //! Declare plugin export functions, should be used before other PIP_PLUGIN_* macros //! \relatedalso PIPluginLoader #define PIP_PLUGIN //! Set user version to check it while loading //! \relatedalso PIPluginLoader #define PIP_PLUGIN_SET_USER_VERSION(version) //! Add pointer to future merge with plugin. Type is integer //! \relatedalso PIPluginLoader #define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) //! Declare function to merge static sections. 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. //! \relatedalso PIPluginLoader #define PIP_PLUGIN_STATIC_SECTION_MERGE //! Mark method to export //! \relatedalso 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 staticSections() const; private: 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; }; class PIP_EXPORT PIPluginLoader { public: typedef int(*FunctionLoaderVersion)(); 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()); //! Destructor ~PIPluginLoader(); //! Load plugin with base filename "name". Loader try prefix "lib" //! and suffix ".dll", ".so" or ".dylib", depends on platform bool load(const PIString & name); //! Unload plugin and free library void unload(); //! 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(); //! Resolve symbol "name" from plugin library void * resolve(const char * name); //! Invoke plugin PIP_PLUGIN_STATIC_SECTION_MERGE function //! on every common type, with "from" - application scope, //! "to" - plugin scope 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