diff --git a/CMakeLists.txt b/CMakeLists.txt index 9165454c..e448f8b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(pip) set(pip_MAJOR 2) set(pip_MINOR 10) -set(pip_REVISION 0) +set(pip_REVISION 1) set(pip_SUFFIX ) set(pip_COMPANY SHS) set(pip_DOMAIN org.SHS) @@ -433,6 +433,9 @@ if (NOT CROSSTOOLS) # Test program if(PIP_UTILS) + #add_library(pip_plugin SHARED "test_plugin.h" "test_plugin.cpp") + #target_link_libraries(pip_plugin pip) + add_executable(pip_test "main.cpp") target_link_libraries(pip_test pip pip_cloud) if (LUA_FOUND) diff --git a/libs/main/core/piincludes.cpp b/libs/main/core/piincludes.cpp index 6b480a21..aa583426 100644 --- a/libs/main/core/piincludes.cpp +++ b/libs/main/core/piincludes.cpp @@ -79,6 +79,22 @@ PIString PIPVersion() { return ret; } + +void piqsort(void * base, size_t num, size_t size, int (*compar)(const void *, const void *)) { + qsort(base, num, size, compar); +} + + +void randomize() { + srand(PISystemTime::current(true).nanoseconds); +} + + +int randomi() { + return rand(); +} + + /*! \class PICout * \brief Class for formatted output similar std::cout * @@ -131,6 +147,9 @@ PIString PIPVersion() { * * packets extractor (\a PIPacketExtractor) * * binary log (\a PIBinaryLog) * * complex I/O point (\a PIConnection) + * * Run-time libraries + * * abstract (\a PILibrary) + * * plugin (\a PIPluginLoader) * * connection quality diagnotic (\a PIDiagnostics) * * command-line arguments parser (\a PICLI) * * math evaluator (\a PIEvaluator) @@ -247,19 +266,3 @@ int main(int argc, char * argv[]) { /*! \page using_advanced Advanced using * Sorry, creativity crysis xD */ - - -void piqsort(void * base, size_t num, size_t size, int (*compar)(const void *, const void *)) { - qsort(base, num, size, compar); -} - - -void randomize() { - srand(PISystemTime::current(true).nanoseconds); -} - - -int randomi() { - return rand(); -} - diff --git a/libs/main/core/pivariantsimple.h b/libs/main/core/pivariantsimple.h index c9b354be..017872c2 100644 --- a/libs/main/core/pivariantsimple.h +++ b/libs/main/core/pivariantsimple.h @@ -43,7 +43,7 @@ public: //static PIMap & registered() {static PIMap ret; return ret;} }; - +/* template class __VariantFunctions__: public __VariantFunctionsBase__ { public: @@ -51,10 +51,10 @@ public: PIString typeName() const final {static PIString ret(typeid(T).name()); return ret;} uint hash() const final {static uint ret = typeName().hash(); return ret;} }; - +*/ template -class __VariantFunctions__::value>::type>: public __VariantFunctionsBase__ { +class __VariantFunctions__/*::value>::type>*/: public __VariantFunctionsBase__ { public: __VariantFunctionsBase__ * instance() final {static __VariantFunctions__ ret; return &ret;} PIString typeName() const final {static PIString ret(typeid(T).name()); return ret;} diff --git a/libs/main/system/piplugin.cpp b/libs/main/system/piplugin.cpp index a711e7d7..e93f6b37 100644 --- a/libs/main/system/piplugin.cpp +++ b/libs/main/system/piplugin.cpp @@ -23,6 +23,140 @@ #include "pifile.h" #include "piincludes_p.h" +/*! \class PIPluginLoader + * \brief Plugin loader + * + * \section PIPluginLoader_sec0 Synopsis + * This class provides several macro to define plugin and %PIPluginLoader - class + * to load and check plugin. + * + * \section PIPluginLoader_sec1 Plugin side + * Plugin is a shared library that can be loaded in run-time. + * This is only 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 + * and plugin with macro \a PIP_PLUGIN_STATIC_SECTION_MERGE. Before + * merge, you should set pointers to that sections with macro + * \a PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr). + * + * \section PIPluginLoader_sec2 Application side + * 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, , lib and + * "dll", "so" and "dylib" extensions, depends on system. + * For example: + * \code + * PIPluginLoader l; + * l.load("foo"); + * \endcode + * On Windows, try to open "foo", "libfoo", "foo.dll" and + * "libfoo.dll". + * 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 cymbols with function + * \a resolve(name), similar to PILibrary. + * \note You should use PIP_PLUGIN_EXPORT and "export "C"" + * with functions you want to use with \a resolve(name)! + * + * \section PIPluginLoader_sec3 Static sections + * 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 + * PIP_PLUGIN_STATIC_SECTION_MERGE() { + * switch (type) { + * ... + * } + * } + * \endcode + * \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 + * static linking, there are many objects in application and you + * should merge their content with this macro. + * + * 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. + * 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. + * + * \section PIPluginLoader_sec4 Examples + * Simple plugin: + * \code + * #include + * + * PIP_PLUGIN + * + * extern "C" { + * PIP_PLUGIN_EXPORT void myFunc() { + * piCout << "Hello plugin!"; + * } + * } + * \endcode + * + * Application: + * \code + * #include + * int main() { + * PIPluginLoader pl; + * pl.load("your_lib"); + * if (pl.isLoaded()) { + * typedef void(*MyFunc)(); + * MyFunc f = (MyFunc)pl.resolve("myFunc"); + * if (f) f(); + * } + * return 0; + * } + * \endcode + * + * Complex plugin: + * \code + * #include + * + * PIStringList global_list; + * + * PIP_PLUGIN + * PIP_PLUGIN_SET_USER_VERSION("1.0.0") + * PIP_PLUGIN_ADD_STATIC_SECTION(1, &global_list) + * + * STATIC_INITIALIZER_BEGIN + * global_list << "plugin_init"; + * STATIC_INITIALIZER_END + * + * PIP_PLUGIN_STATIC_SECTION_MERGE { + * PIStringList * sfrom = (PIStringList*)from, * sto = (PIStringList*)to; + * *sto << *sfrom; + * sto->removeDuplicates(); + * } + * \endcode + * + * Application: + * \code + * #include + * + * PIStringList global_list; + * + * PIP_PLUGIN_SET_USER_VERSION("1.0.0"); + * PIP_PLUGIN_ADD_STATIC_SECTION(1, &global_list); + * + * int main() { + * global_list << "app"; + * PIPluginLoader pl; + * pl.load("your_lib"); + * pl.mergeStatic(); + * piCout << "list =" << global_list; + * return 0; + * } + * \endcode + * + */ + #define STR_WF(s) #s #define STR(s) STR_WF(s) @@ -84,7 +218,7 @@ PIPluginLoader::~PIPluginLoader() { bool PIPluginLoader::load(const PIString & name) { unload(); if (!lib.load(findLibrary(name))) return false; - piCout << "loading" << lib.path() << "..."; + //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__); @@ -142,6 +276,11 @@ void PIPluginLoader::unload() { } +bool PIPluginLoader::isLoaded() const { + return loaded; +} + + PIString PIPluginLoader::libPath() { return lib.path(); } diff --git a/libs/main/system/piplugin.h b/libs/main/system/piplugin.h index 99a1576c..df313b2c 100644 --- a/libs/main/system/piplugin.h +++ b/libs/main/system/piplugin.h @@ -19,7 +19,7 @@ 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 @@ -32,12 +32,15 @@ //! 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 -#define PIP_PLUGIN_SET_USER_VERSION(v) +//! \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 @@ -47,8 +50,13 @@ //! (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 @@ -136,6 +144,9 @@ public: //! Unload plugin and free library void unload(); + //! Returns if plugin is successfully loaded + bool isLoaded() const; + //! Returns loaded plugin library path PIString libPath();