# HG changeset patch # User Sebastien Jodogne # Date 1402768071 -7200 # Node ID d44b845c1c895819c3fbda2459534573a27a41e1 # Parent 4066e6f2d134fb214f99643df662b2db9e9c530a recursive scan for plugins diff -r 4066e6f2d134 -r d44b845c1c89 Plugins/Engine/PluginsManager.cpp --- a/Plugins/Engine/PluginsManager.cpp Sat Jun 14 19:20:38 2014 +0200 +++ b/Plugins/Engine/PluginsManager.cpp Sat Jun 14 19:47:51 2014 +0200 @@ -35,6 +35,16 @@ #include #include #include +#include + +#ifdef WIN32 +#define PLUGIN_EXTENSION ".dll" +#elif defined(__linux) +#define PLUGIN_EXTENSION ".so" +#else +#error Support your platform here +#endif + namespace Orthanc { @@ -79,6 +89,30 @@ } + static const char* CallGetName(SharedLibrary& plugin) + { + typedef const char* (*GetName) (); + + GetName getName; + *(void **) (&getName) = plugin.GetFunction("OrthancPluginGetName"); + assert(getName != NULL); + + return getName(); + } + + + static const char* CallGetVersion(SharedLibrary& plugin) + { + typedef const char* (*GetVersion) (); + + GetVersion getVersion; + *(void **) (&getVersion) = plugin.GetFunction("OrthancPluginGetVersion"); + assert(getVersion != NULL); + + return getVersion(); + } + + static void LogError(const char* str) { LOG(ERROR) << str; @@ -114,32 +148,95 @@ { for (Plugins::iterator it = plugins_.begin(); it != plugins_.end(); it++) { - if (*it != NULL) + if (it->second != NULL) { - CallFinalize(**it); - delete *it; + CallFinalize(*(it->second)); + delete it->second; } } } + + static bool IsOrthancPlugin(SharedLibrary& library) + { + return (library.HasFunction("OrthancPluginInitialize") && + library.HasFunction("OrthancPluginFinalize") && + library.HasFunction("OrthancPluginGetName") && + library.HasFunction("OrthancPluginGetVersion")); + } + void PluginsManager::RegisterPlugin(const std::string& path) { std::auto_ptr plugin(new SharedLibrary(path)); - if (!plugin->HasFunction("OrthancPluginInitialize") || - !plugin->HasFunction("OrthancPluginFinalize")) + if (!IsOrthancPlugin(*plugin)) { LOG(ERROR) << "Plugin " << plugin->GetPath() << " does not declare the proper entry functions"; throw OrthancException(ErrorCode_SharedLibrary); } - LOG(WARNING) << "Registering plugin " << path; + std::string name(CallGetName(*plugin)); + if (plugins_.find(name) != plugins_.end()) + { + LOG(ERROR) << "Plugin '" << name << "' already registered"; + throw OrthancException(ErrorCode_SharedLibrary); + } + + LOG(WARNING) << "Registering plugin '" << name + << "' (version " << CallGetVersion(*plugin) << ")"; CallInitialize(*plugin, context_); - plugins_.push_back(plugin.release()); + plugins_[name] = plugin.release(); + } + + + void PluginsManager::ScanFolderForPlugins(const std::string& path, + bool isRecursive) + { + using namespace boost::filesystem; + + if (!exists(path)) + { + return; + } + + LOG(INFO) << "Scanning folder " << path << " for plugins"; + + directory_iterator end_it; // default construction yields past-the-end + for (directory_iterator it(path); + it != end_it; + ++it) + { + if (is_directory(it->status())) + { + if (isRecursive) + { + ScanFolderForPlugins(it->path().string(), true); + } + } + else + { + if (boost::filesystem::extension(it->path()) == PLUGIN_EXTENSION) + { + LOG(INFO) << "Found a shared library: " << it->path(); + + try + { + SharedLibrary plugin(it->path().string()); + if (IsOrthancPlugin(plugin)) + { + RegisterPlugin(it->path().string()); + } + } + catch (OrthancException&) + { + } + } + } + } } } diff -r 4066e6f2d134 -r d44b845c1c89 Plugins/Engine/PluginsManager.h --- a/Plugins/Engine/PluginsManager.h Sat Jun 14 19:20:38 2014 +0200 +++ b/Plugins/Engine/PluginsManager.h Sat Jun 14 19:47:51 2014 +0200 @@ -35,14 +35,14 @@ #include "SharedLibrary.h" #include "../OrthancCPlugin/OrthancCPlugin.h" -#include +#include namespace Orthanc { class PluginsManager : boost::noncopyable { private: - typedef std::list Plugins; + typedef std::map Plugins; OrthancPluginContext context_; Plugins plugins_; @@ -53,5 +53,8 @@ ~PluginsManager(); void RegisterPlugin(const std::string& path); + + void ScanFolderForPlugins(const std::string& path, + bool isRecursive); }; } diff -r 4066e6f2d134 -r d44b845c1c89 Plugins/OrthancCPlugin/OrthancCPlugin.h --- a/Plugins/OrthancCPlugin/OrthancCPlugin.h Sat Jun 14 19:20:38 2014 +0200 +++ b/Plugins/OrthancCPlugin/OrthancCPlugin.h Sat Jun 14 19:47:51 2014 +0200 @@ -78,9 +78,11 @@ /** - Each plugin must define 2 functions, whose signature is: + Each plugin must define 4 functions, whose signature is: - int32_t OrthancPluginInitialize(const OrthancPluginContext*); - void OrthancPluginFinalize(); + - const char* OrthancPluginGetName(); + - const char* OrthancPluginGetVersion(); nm -C -D --defined-only libPluginTest.so **/ diff -r 4066e6f2d134 -r d44b845c1c89 Resources/Samples/Plugins/Basic/Plugin.c --- a/Resources/Samples/Plugins/Basic/Plugin.c Sat Jun 14 19:20:38 2014 +0200 +++ b/Resources/Samples/Plugins/Basic/Plugin.c Sat Jun 14 19:47:51 2014 +0200 @@ -53,3 +53,14 @@ } +ORTHANC_PLUGINS_API const char* OrthancPluginGetName() +{ + return "sample"; +} + + +ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() +{ + return "1.0"; +} + diff -r 4066e6f2d134 -r d44b845c1c89 UnitTestsSources/PluginsTests.cpp --- a/UnitTestsSources/PluginsTests.cpp Sat Jun 14 19:20:38 2014 +0200 +++ b/UnitTestsSources/PluginsTests.cpp Sat Jun 14 19:47:51 2014 +0200 @@ -66,7 +66,10 @@ #error Support your platform here #elif defined(__linux) - manager.RegisterPlugin("./libPluginTest.so"); + //manager.RegisterPlugin("./libPluginTest.so"); + //ASSERT_THROW(manager.RegisterPlugin("./libPluginTest.so"), OrthancException); + + manager.ScanFolderForPlugins(".", true); #else #error Support your platform here