From 62b545128f37746c343760e464872655b5523c6f Mon Sep 17 00:00:00 2001 From: erihel Date: Sun, 12 Aug 2012 18:37:11 +0200 Subject: * Final changes to plugin interface * Added doxygen comments to plugin manager and plugin loader --- src/plugins/plugininterface.h | 34 ++++++++++++++++++++++++++++--- src/plugins/pluginloader.cpp | 17 +++++++++++++--- src/plugins/pluginloader.h | 42 ++++++++++++++++++++++++++++++++++++++- src/plugins/pluginmanager.cpp | 22 ++++++++++++++------ src/plugins/pluginmanager.h | 33 ++++++++++++++++++++++++++++++ src/plugins/test/manager_test.cpp | 7 +++++++ 6 files changed, 142 insertions(+), 13 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/plugininterface.h b/src/plugins/plugininterface.h index bf4e040..b8adddc 100644 --- a/src/plugins/plugininterface.h +++ b/src/plugins/plugininterface.h @@ -16,22 +16,50 @@ // plugininterface.h +/** + * @file plugin/plugininterface.h + * @brief Generic plugin interface + */ #pragma once +#include #define PLUGIN_INTERFACE(class_type) \ static class_type* Plugin##class_type; \ extern "C" void InstallPluginEntry() { Plugin##class_type = new class_type(); Plugin##class_type->InstallPlugin(); } \ - extern "C" void UninstallPluginEntry() { Plugin##class_type->UninstallPlugin(); delete Plugin##class_type; } \ + extern "C" bool UninstallPluginEntry(std::string &reason) { bool result = Plugin##class_type->UninstallPlugin(reason); \ + if (!result) \ + return false; \ + delete Plugin##class_type; \ + return true; } \ extern "C" CPluginInterface* GetPluginInterfaceEntry() { return static_cast(Plugin##class_type); } +/** +* @class CPluginInterface +* +* @brief Generic plugin interface. All plugins that will be managed by plugin manager have to derive from this class. +* +*/ class CPluginInterface { public: - virtual char* PluginName() = 0; + /** Function to get plugin name or description + * @return returns plugin name + */ + virtual std::string PluginName() = 0; + + /** Function to get plugin version. 1 means version 0.01, 2 means 0.02 etc. + * @return number indicating plugin version + */ virtual int PluginVersion() = 0; + + /** Function to initialize plugin + */ virtual void InstallPlugin() = 0; - virtual void UninstallPlugin() = 0; + + /** Function called before removing plugin + */ + virtual bool UninstallPlugin(std::string &) = 0; }; diff --git a/src/plugins/pluginloader.cpp b/src/plugins/pluginloader.cpp index 8893b56..fd8ce74 100644 --- a/src/plugins/pluginloader.cpp +++ b/src/plugins/pluginloader.cpp @@ -28,11 +28,11 @@ CPluginLoader::CPluginLoader(std::string filename) } -char* CPluginLoader::GetName() +std::string CPluginLoader::GetName() { if (mLoaded) return mInterface->PluginName(); - return nullptr; + return "(not loaded)"; } @@ -57,12 +57,18 @@ bool CPluginLoader::UnloadPlugin() return true; } - void (*uninstall)() = (void (*)()) lt_dlsym(mHandle, "UninstallPluginEntry"); + bool (*uninstall)(std::string &) = (bool (*)(std::string &)) lt_dlsym(mHandle, "UninstallPluginEntry"); if (!uninstall) { GetLogger()->Error("Error getting UninstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); return false; } + std::string reason; + if (!uninstall(reason)) { + GetLogger()->Error("Could not unload plugin %s: %s\n", mFilename.c_str(), reason.c_str()); + return false; + } + lt_dlclose(mHandle); mLoaded = false; return true; @@ -71,6 +77,11 @@ bool CPluginLoader::UnloadPlugin() bool CPluginLoader::LoadPlugin() { + if (mFilename.length() == 0) { + GetLogger()->Warn("No plugin filename specified.\n"); + return false; + } + mHandle = lt_dlopenext(mFilename.c_str()); if (!mHandle) { GetLogger()->Error("Error loading plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); diff --git a/src/plugins/pluginloader.h b/src/plugins/pluginloader.h index 873d30a..40b19da 100644 --- a/src/plugins/pluginloader.h +++ b/src/plugins/pluginloader.h @@ -16,6 +16,10 @@ // pluginloader.h +/** + * @file plugin/pluginloader.h + * @brief Plugin loader interface + */ #pragma once @@ -27,16 +31,52 @@ #include "plugininterface.h" +/** +* @class CPluginLoader +* +* @brief Plugin loader interface. Plugin manager uses this class to load plugins. +* +*/ class CPluginLoader { public: + /** Class contructor + * @param std::string plugin filename + */ CPluginLoader(std::string); - char* GetName(); + /** Function to get plugin name or description + * @return returns plugin name + */ + std::string GetName(); + + /** Function to get plugin version + * @return returns plugin version + */ int GetVersion(); + + /** Function to unload plugin + * @return returns true on success + */ bool UnloadPlugin(); + + /** Function to load plugin + * @return returns true on success + */ bool LoadPlugin(); + + /** Function to check if plugin is loaded + * @return returns true if plugin is loaded + */ bool IsLoaded(); + + /** Function to set plugin filename + * @return returns true on success. Action can fail if plugin was loaded and cannot be unloaded + */ bool SetFilename(std::string); + + /** Function to get plugin filename + * @return returns plugin filename + */ std::string GetFilename(); diff --git a/src/plugins/pluginmanager.cpp b/src/plugins/pluginmanager.cpp index ab9d8ad..470ac2f 100644 --- a/src/plugins/pluginmanager.cpp +++ b/src/plugins/pluginmanager.cpp @@ -60,7 +60,7 @@ bool CPluginManager::LoadPlugin(std::string filename) loader->SetFilename(dir + "/" + filename); result = loader->LoadPlugin(); if (result) { - GetLogger()->Info("Plugin %s (%s) version %0.2f loaded!\n", filename.c_str(), loader->GetName(), loader->GetVersion() / 100.0f); + GetLogger()->Info("Plugin %s (%s) version %0.2f loaded!\n", filename.c_str(), loader->GetName().c_str(), loader->GetVersion() / 100.0f); m_plugins.push_back(loader); break; } @@ -102,13 +102,23 @@ bool CPluginManager::RemoveSearchDirectory(std::string dir) bool CPluginManager::UnloadAllPlugins() { - for (CPluginLoader *plugin : m_plugins) { - GetLogger()->Info("Trying to unload plugin %s (%s)...\n", plugin->GetFilename().c_str(), plugin->GetName()); - plugin->UnloadPlugin(); + bool allOk = true; + std::vector::iterator it; + for (it = m_plugins.begin(); it != m_plugins.end(); it++) { + CPluginLoader *plugin = *it; + bool result; + + GetLogger()->Info("Trying to unload plugin %s (%s)...\n", plugin->GetFilename().c_str(), plugin->GetName().c_str()); + result = plugin->UnloadPlugin(); + if (!result) { + allOk = false; + continue; + } delete plugin; + m_plugins.erase(it); } - m_plugins.clear(); - return true; + + return allOk; } diff --git a/src/plugins/pluginmanager.h b/src/plugins/pluginmanager.h index d267238..e425c62 100644 --- a/src/plugins/pluginmanager.h +++ b/src/plugins/pluginmanager.h @@ -16,6 +16,10 @@ // pluginmanager.h +/** + * @file plugin/pluginmanager.h + * @brief Plugin manager class. + */ #pragma once @@ -31,19 +35,48 @@ #include "pluginloader.h" +/** +* @class CPluginManager +* +* @brief Plugin manager class. Plugin manager can load plugins from colobot.ini or manually specified files. +* +*/ class CPluginManager : public CSingleton { public: CPluginManager(); ~CPluginManager(); + /** Function loads plugin list and path list from profile file + */ void LoadFromProfile(); + /** Function loads specified plugin + * @param std::string plugin filename + * @return returns true on success + */ bool LoadPlugin(std::string); + + /** Function unloads specified plugin + * @param std::string plugin filename + * @return returns true on success + */ bool UnloadPlugin(std::string); + /** Function adds path to be checked when searching for plugin file. If path was already added it will be ignored + * @param std::string plugin search path + * @return returns true on success + */ bool AddSearchDirectory(std::string); + + /** Function removes path from list + * @param std::string plugin search path + * @return returns true on success + */ bool RemoveSearchDirectory(std::string); + /** Function tries to unload all plugins + * @return returns true on success + */ bool UnloadAllPlugins(); private: diff --git a/src/plugins/test/manager_test.cpp b/src/plugins/test/manager_test.cpp index 9b3f472..d921c1d 100644 --- a/src/plugins/test/manager_test.cpp +++ b/src/plugins/test/manager_test.cpp @@ -15,8 +15,15 @@ int main() { GetLogger()->Error("Config not found!\n"); return 1; } + mgr->LoadFromProfile(); CSoundInterface *sound = static_cast(CInstanceManager::GetInstancePointer()->SearchInstance(CLASS_SOUND)); + + if (!sound) { + GetLogger()->Error("Sound not loaded!\n"); + return 2; + } + sound->Create(true); mgr->UnloadAllPlugins(); -- cgit v1.2.3-1-g7c22