/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #ifndef __PLUGIN_MANAGER__ #define __PLUGIN_MANAGER__ #include "shared/shared_library.h" #include "plugin/shared_systems.h" #include "container/nlist.h" #include "nstring/nstring.h" #include "platform.h" namespace GS { static const int PluginLoadOk = 0; static const int PluginLoadError = 1; static const int PluginMissingClass = 2; static const int PluginClassError = 3; static const int PluginMissingVersion = 4; static const int PluginVersionError = 5; static const int PluginInterfaceError = 6; /*! @short Plugin manager @author Emmanuel Julien (ejulien@owloh.com) */ template class PluginManager { typedef void SetSharedSystems(SharedSystems &); typedef T *Factory(); typedef const char *GetPluginClass(); typedef uint GetPluginVersion(); public: struct Plugin { String path; AutoPtr shared_lib; }; private: AutoList plugins; public: /// Return a new instance to concrete interface the plugin implements. T *CreatePluginInterface(Plugin *p) { Factory *p_factory = p ? (Factory *)p->shared_lib->GetFunctionPointer("createPluginInterface") : 0; return p_factory ? p_factory() : 0; } /* @short Load a plugin. The plugin is dynamically loaded from the specified path and its class and version are checked for compatibility with the host interface class and version. A return code can be passed to get more information on failure. */ Plugin *LoadPlugin(const char *path, int *code = 0) { AutoPtr p(new Plugin); if (p.IsNull()) return 0; if (code) *code = PluginLoadOk; #define Error(V) { if (code) *code = V; return 0; } p->shared_lib = Platform::Get().LoadSharedLibrary(path); if (p->shared_lib.IsNull()) Error(PluginLoadError); GetPluginClass *get_plugin_class = (GetPluginClass *)p->shared_lib->GetFunctionPointer("getPluginClass"); GetPluginVersion *get_plugin_version = (GetPluginVersion *)p->shared_lib->GetFunctionPointer("getPluginVersion"); SetSharedSystems *set_shared_systems = (SetSharedSystems *)p->shared_lib->GetFunctionPointer("setSharedSystems"); if (!get_plugin_class) Error(PluginMissingClass); if (!get_plugin_version) Error(PluginMissingVersion); if (!set_shared_systems) Error(PluginInterfaceError); if (String(T::GetPluginClass()) != get_plugin_class()) Error(PluginClassError); if (T::GetPluginVersion() != get_plugin_version()) Error(PluginVersionError); // Set the shared platform pointer. SharedSystems shared; set_shared_systems(shared); p->path = path; plugins.Add(p); return p.Detach(); } }; } // GS #endif // __PLUGIN_MANAGER__