/* 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 PIP_FREERTOS #include "piplugin.h" #include "pifile.h" #include "piincludes_p.h" #define STR_WF(s) #s #define STR(s) STR_WF(s) PIPluginInfo * PIPluginInfo::instance() { static PIPluginInfo ret; return &ret; } PIPluginLoader::PIPluginLoader(const PIString & name) { func_loader_version = nullptr; func_plugin_info = nullptr; func_static_merge = nullptr; plugin_info = nullptr; loaded = false; if (!name.isEmpty()) load(name); } PIPluginLoader::~PIPluginLoader() { lib.unload(); } bool PIPluginLoader::load(const PIString & name) { unload(); if (!lib.load(findLibrary(name))) 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(); 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(); 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()->user_version.size_s() > 1) { PIString pversion = plugin_info->user_version, lversion = PIPluginInfo::instance()->user_version; if (pversion != lversion) { piCout << "Load plugin \"" << name << "\" error: invalid user version: plugin" << pversion << "!=" << lversion; unload(); return false; } } func_static_merge = (FunctionStaticMerge)lib.resolve(STR(__PIP_PLUGIN_STATIC_MERGE_FUNC__)); if (func_static_merge) { piCout << PIPluginInfo::instance()->static_sections.keys() << plugin_info->static_sections.keys(); auto it = PIPluginInfo::instance()->static_sections.makeIterator(); while (it.next()) { if (!plugin_info->static_sections.contains(it.key())) continue; func_static_merge(it.key(), plugin_info->static_sections.value(it.key()), it.value()); } } loaded = true; return true; } void PIPluginLoader::unload() { lib.unload(); plugin_info = nullptr; loaded = false; } PIString PIPluginLoader::libPath() { return lib.path(); } void * PIPluginLoader::resolve(const char * name) { if (!loaded) return nullptr; return lib.resolve(name); } void PIPluginLoader::mergeStatic() { if (!loaded || !func_static_merge || !plugin_info) return; auto it = PIPluginInfo::instance()->static_sections.makeIterator(); while (it.next()) { if (!plugin_info->static_sections.contains(it.key())) continue; func_static_merge(it.key(), it.value(), plugin_info->static_sections.value(it.key())); } } PIString PIPluginLoader::findLibrary(const PIString & path) { static const PIStringList prefixes({"", "lib"}); static const PIStringList suffixes({"", libExtension()}); PIFile::FileInfo fi(path); PIString dir = fi.dir(), name = fi.name(); piForeachC (PIString & p, prefixes) { piForeachC (PIString & s, suffixes) { PIString fn = dir + p + name + s; if (PIFile::isExists(fn)) return fn; } } return PIString(); } PIString PIPluginLoader::libExtension() { return #ifdef WINDOWS ".dll" #elif defined(MAC_OS) ".dylib" #else ".so" #endif ; } #endif // PIP_FREERTOS