# HG changeset patch # User Sebastien Jodogne # Date 1403075908 -7200 # Node ID 7000fc86fe624eacef58dedfb812923632fd1b5b # Parent bafc9d592632bfa3756fa640a7c2a89ec1a6ac41 improved plugin api diff -r bafc9d592632 -r 7000fc86fe62 Plugins/Engine/IPluginServiceProvider.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Engine/IPluginServiceProvider.h Wed Jun 18 09:18:28 2014 +0200 @@ -0,0 +1,49 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../OrthancCPlugin/OrthancCPlugin.h" + +#include + +namespace Orthanc +{ + class IPluginServiceProvider : boost::noncopyable + { + public: + virtual ~IPluginServiceProvider(); + + virtual bool Handle(OrthancPluginService service, + const void* parameters) = 0; + }; +} diff -r bafc9d592632 -r 7000fc86fe62 Plugins/Engine/PluginsManager.cpp --- a/Plugins/Engine/PluginsManager.cpp Tue Jun 17 17:43:39 2014 +0200 +++ b/Plugins/Engine/PluginsManager.cpp Wed Jun 18 09:18:28 2014 +0200 @@ -132,27 +132,47 @@ } - static void LogError(const char* str) + int32_t PluginsManager::InvokeService(OrthancPluginContext* context, + OrthancPluginService service, + const void* parameters) { - LOG(ERROR) << str; + switch (service) + { + case OrthancPluginService_LogError: + LOG(ERROR) << reinterpret_cast(parameters); + return 0; + + case OrthancPluginService_LogWarning: + LOG(WARNING) << reinterpret_cast(parameters); + return 0; + + case OrthancPluginService_LogInfo: + LOG(INFO) << reinterpret_cast(parameters); + return 0; + + default: + break; + } + + PluginsManager* that = reinterpret_cast(context->pluginsManager); + + if (that->HasServiceProvider() && + that->serviceProvider_->Handle(service, parameters)) + { + return 0; + } + + LOG(ERROR) << "Plugin invoking unknown service " << service; + return -1; } - static void LogWarning(const char* str) - { - LOG(WARNING) << str; - } - - static void LogInfo(const char* str) - { - LOG(INFO) << str; - } void PluginsManager::RegisterRestCallback(const OrthancPluginContext* context, const char* pathRegularExpression, OrthancPluginRestCallback callback) { LOG(INFO) << "Plugin has registered a REST callback on: " << pathRegularExpression; - PluginsManager* manager = reinterpret_cast(context->pimpl); + PluginsManager* manager = reinterpret_cast(context->pluginsManager); manager->restCallbacks_.push_back(std::make_pair(pathRegularExpression, callback)); } @@ -167,15 +187,14 @@ } - PluginsManager::PluginsManager() + PluginsManager::PluginsManager() : + serviceProvider_(NULL) { memset(&context_, 0, sizeof(context_)); - context_.pimpl = this; + context_.pluginsManager = this; context_.orthancVersion = ORTHANC_VERSION; context_.FreeBuffer = ::free; - context_.LogError = LogError; - context_.LogWarning = LogWarning; - context_.LogInfo = LogInfo; + context_.InvokeService = InvokeService; context_.RegisterRestCallback = RegisterRestCallback; context_.AnswerBuffer = AnswerBuffer; } @@ -279,4 +298,17 @@ } } } + + + IPluginServiceProvider& PluginsManager::GetServiceProvider() const + { + if (!HasServiceProvider()) + { + throw OrthancException(ErrorCode_BadRequest); + } + else + { + return *serviceProvider_; + } + } } diff -r bafc9d592632 -r 7000fc86fe62 Plugins/Engine/PluginsManager.h --- a/Plugins/Engine/PluginsManager.h Tue Jun 17 17:43:39 2014 +0200 +++ b/Plugins/Engine/PluginsManager.h Wed Jun 18 09:18:28 2014 +0200 @@ -33,7 +33,7 @@ #pragma once #include "SharedLibrary.h" -#include "../OrthancCPlugin/OrthancCPlugin.h" +#include "IPluginServiceProvider.h" #include #include @@ -47,9 +47,15 @@ private: typedef std::map Plugins; + OrthancPluginContext context_; Plugins plugins_; RestCallbacks restCallbacks_; + IPluginServiceProvider *serviceProvider_; + + static int32_t InvokeService(OrthancPluginContext* context, + OrthancPluginService service, + const void* parameters); static void RegisterRestCallback(const OrthancPluginContext* context, const char* path, @@ -65,6 +71,18 @@ void ScanFolderForPlugins(const std::string& path, bool isRecursive); + void SetServiceProvider(IPluginServiceProvider& provider) + { + serviceProvider_ = &provider; + } + + bool HasServiceProvider() const + { + return serviceProvider_ != NULL; + } + + IPluginServiceProvider& GetServiceProvider() const; + const RestCallbacks& GetRestCallbacks() const { return restCallbacks_; diff -r bafc9d592632 -r 7000fc86fe62 Plugins/OrthancCPlugin/OrthancCPlugin.h --- a/Plugins/OrthancCPlugin/OrthancCPlugin.h Tue Jun 17 17:43:39 2014 +0200 +++ b/Plugins/OrthancCPlugin/OrthancCPlugin.h Wed Jun 18 09:18:28 2014 +0200 @@ -33,13 +33,6 @@ #pragma once -#ifdef _MSC_VER -#include "../../Resources/VisualStudio/stdint.h" -#else -#include -#endif - - #ifdef WIN32 #define ORTHANC_PLUGINS_API __declspec(dllexport) #else @@ -47,9 +40,59 @@ #endif + +/******************************************************************** + ** Check that function inlining is properly supported. The use of + ** inlining is required, to avoid the duplication of object code + ** between two compilation modules that would use the Orthanc Plugin + ** API. + ********************************************************************/ + +/* If the auto-detection of the "inline" keyword below does not work + automatically and that your compiler is known to properly support + inlining, uncomment the following #define and adapt the definition + of "static inline". */ + +/* #define ORTHANC_PLUGIN_INLINE static inline */ + +#ifndef ORTHANC_PLUGIN_INLINE +# if __STDC_VERSION__ >= 199901L +/* This is C99 or above: http://predef.sourceforge.net/prestd.html */ +# define ORTHANC_PLUGIN_INLINE static inline +# elif defined(__cplusplus) +/* This is C++ */ +# define ORTHANC_PLUGIN_INLINE static inline +# elif defined(__GNUC__) +/* This is GCC running in C89 mode */ +# define ORTHANC_PLUGIN_INLINE static __inline +# elif defined(_MSC_VER) +/* This is Visual Studio running in C89 mode */ +# define ORTHANC_PLUGIN_INLINE static __inline +# else +# error Your compiler is not known to support the "inline" keyword +# endif +#endif + + + +/******************************************************************** + ** Inclusion of standard libaries. + ********************************************************************/ + +#ifdef _MSC_VER +#include "../../Resources/VisualStudio/stdint.h" +#else +#include +#endif + #include + +/******************************************************************** + ** Definition of the Orthanc Plugin API. + ********************************************************************/ + #ifdef __cplusplus extern "C" { @@ -65,8 +108,12 @@ OrthancPluginHttpMethod_Delete = 4 } OrthancPluginHttpMethod; - typedef int32_t (*OrthancPluginService) (const char* serviceName, - const void* serviceParameters); + typedef enum + { + OrthancPluginService_LogInfo = 1, + OrthancPluginService_LogWarning = 2, + OrthancPluginService_LogError = 3 + } OrthancPluginService; typedef int32_t (*OrthancPluginRestCallback) (OrthancPluginRestOutput* output, OrthancPluginHttpMethod method, @@ -78,15 +125,13 @@ typedef struct OrthancPluginContext_t { - void* pimpl; + void* pluginsManager; const char* orthancVersion; void (*FreeBuffer) (void* buffer); - - /* Logging functions */ - void (*LogError) (const char* str); - void (*LogWarning) (const char* str); - void (*LogInfo) (const char* str); + int32_t (*InvokeService) (struct OrthancPluginContext_t* context, + OrthancPluginService service, + const void* parameters); /* REST API */ void (*RegisterRestCallback) (const struct OrthancPluginContext_t* context, @@ -100,6 +145,28 @@ } OrthancPluginContext; + ORTHANC_PLUGIN_INLINE void OrthancPluginLogError(OrthancPluginContext* context, + const char* str) + { + context->InvokeService(context, OrthancPluginService_LogError, str); + } + + + ORTHANC_PLUGIN_INLINE void OrthancPluginLogWarning(OrthancPluginContext* context, + const char* str) + { + context->InvokeService(context, OrthancPluginService_LogWarning, str); + } + + + ORTHANC_PLUGIN_INLINE void OrthancPluginLogInfo(OrthancPluginContext* context, + const char* str) + { + context->InvokeService(context, OrthancPluginService_LogInfo, str); + } + + + /** Each plugin must define 4 functions, whose signature are: - int32_t OrthancPluginInitialize(const OrthancPluginContext*); diff -r bafc9d592632 -r 7000fc86fe62 Resources/Samples/Plugins/Basic/Plugin.c --- a/Resources/Samples/Plugins/Basic/Plugin.c Tue Jun 17 17:43:39 2014 +0200 +++ b/Resources/Samples/Plugins/Basic/Plugin.c Wed Jun 18 09:18:28 2014 +0200 @@ -30,7 +30,7 @@ #include #include -static const OrthancPluginContext* context = NULL; +static OrthancPluginContext* context = NULL; ORTHANC_PLUGINS_API int32_t Callback(OrthancPluginRestOutput* output, @@ -46,29 +46,29 @@ uint32_t i; sprintf(buffer, "Callback on URL [%s] with body [%s]", url, body); - context->LogInfo(buffer); + OrthancPluginLogInfo(context, buffer); context->AnswerBuffer(output, buffer, strlen(buffer), "text/plain"); for (i = 0; i < getSize; i++) { sprintf(buffer, " [%s] = [%s]", getKeys[i], getValues[i]); - context->LogInfo(buffer); + OrthancPluginLogInfo(context, buffer); } return 1; } -ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(const OrthancPluginContext* c) +ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c) { char info[1024]; context = c; - context->LogWarning("Plugin is initializing"); + OrthancPluginLogWarning(context, "Plugin is initializing"); sprintf(info, "The version of Orthanc is '%s'", context->orthancVersion); - context->LogInfo(info); + OrthancPluginLogInfo(context, info); context->RegisterRestCallback(c, "/plu.*/hello", Callback); @@ -78,7 +78,7 @@ ORTHANC_PLUGINS_API void OrthancPluginFinalize() { - context->LogWarning("Plugin is finalizing"); + OrthancPluginLogWarning(context, "Plugin is finalizing"); }