Mercurial > hg > orthanc
changeset 6114:61e298df01be
added the skeleton of a C++ plugin
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 20 May 2025 09:48:38 +0200 |
parents | 4e7f565e2604 |
children | 9d94f6744753 |
files | OrthancServer/Plugins/Samples/CppSkeleton/CMakeLists.txt OrthancServer/Plugins/Samples/CppSkeleton/EmbeddedResources/app.js OrthancServer/Plugins/Samples/CppSkeleton/NOTES.txt OrthancServer/Plugins/Samples/CppSkeleton/Plugin.cpp OrthancServer/Plugins/Samples/CppSkeleton/Resources/SyncOrthancFolder.py |
diffstat | 5 files changed, 468 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Samples/CppSkeleton/CMakeLists.txt Tue May 20 09:48:38 2025 +0200 @@ -0,0 +1,200 @@ +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2025 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +cmake_minimum_required(VERSION 2.8) + +project(OrthancSkeleton) + +set(ORTHANC_PLUGIN_VERSION "mainline") +set(ORTHANC_PLUGIN_NAME "skeleton") + +if (ORTHANC_PLUGIN_VERSION STREQUAL "mainline") + set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "mainline") + set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") +else() + set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "1.12.7") + set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") +endif() + + +# Parameters of the build +set(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)") +set(STANDALONE_BUILD ON CACHE BOOL "Standalone build (all the resources are embedded, necessary for releases)") +set(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages") +set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc framework (can be \"system\", \"hg\", \"archive\", \"web\" or \"path\")") +set(ORTHANC_FRAMEWORK_VERSION "${ORTHANC_FRAMEWORK_DEFAULT_VERSION}" CACHE STRING "Version of the Orthanc framework") +set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") +set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") + + +# Advanced parameters to fine-tune linking against system libraries +set(USE_SYSTEM_ORTHANC_SDK ON CACHE BOOL "Use the system version of the Orthanc plugin SDK") +set(ORTHANC_FRAMEWORK_STATIC OFF CACHE BOOL "If linking against the Orthanc framework system library, indicates whether this library was statically linked") +mark_as_advanced(ORTHANC_FRAMEWORK_STATIC) + + +# Download and setup the Orthanc framework +if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "path") + include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/DownloadOrthancFramework.cmake) +else() + include(${CMAKE_SOURCE_DIR}/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake) +endif() + + +if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "system") + if (ORTHANC_FRAMEWORK_USE_SHARED) + include(FindBoost) + find_package(Boost COMPONENTS filesystem regex thread) + + if (NOT Boost_FOUND) + message(FATAL_ERROR "Unable to locate Boost on this system") + endif() + + link_libraries(${Boost_LIBRARIES} jsoncpp) + endif() + + link_libraries(${ORTHANC_FRAMEWORK_LIBRARIES}) +else() + include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkParameters.cmake) + + set(ENABLE_LOCALE OFF) # Disable support for locales (notably in Boost) + set(ENABLE_MODULE_JOBS OFF CACHE INTERNAL "") + set(ENABLE_MODULE_DICOM ON CACHE INTERNAL "") + + include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkConfiguration.cmake) + include_directories(${ORTHANC_FRAMEWORK_ROOT}) +endif() + + +if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "path") + include(${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Samples/Common/OrthancPluginsExports.cmake) + include_directories(${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Samples/Common/) + + set(ORTHANC_PLUGINS_SOURCES + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp + ) +else() + include(${CMAKE_SOURCE_DIR}/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake) + include_directories(${CMAKE_SOURCE_DIR}/Resources/Orthanc/Plugins/) + + set(ORTHANC_PLUGINS_SOURCES + ${CMAKE_SOURCE_DIR}/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp + ) +endif() + + +# Check that the Orthanc SDK headers are available +if (STATIC_BUILD OR NOT USE_SYSTEM_ORTHANC_SDK) + if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "path") + include_directories(${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Include) + else() + include_directories(${CMAKE_SOURCE_DIR}/Resources/Orthanc/Sdk-1.0.0) + endif() +else () + CHECK_INCLUDE_FILE_CXX(orthanc/OrthancCPlugin.h HAVE_ORTHANC_H) + if (NOT HAVE_ORTHANC_H) + message(FATAL_ERROR "Please install the headers of the Orthanc plugins SDK") + endif() +endif() + + +if (STANDALONE_BUILD) + add_definitions( + -DORTHANC_STANDALONE=1 + ) + set(EMBEDDED_RESOURCES + PLUGIN_RESOURCES ${CMAKE_SOURCE_DIR}/EmbeddedResources/ + ) +else() + add_definitions( + -DORTHANC_STANDALONE=0 + -DPLUGIN_RESOURCES_PATH="${CMAKE_SOURCE_DIR}/EmbeddedResources/" + ) +endif() + + +message("Setting the version of the library to ${ORTHANC_PLUGIN_VERSION}") + +add_definitions( + -DHAS_ORTHANC_EXCEPTION=1 + -DORTHANC_PLUGIN_NAME="${ORTHANC_PLUGIN_NAME}" + -DORTHANC_PLUGIN_VERSION="${ORTHANC_PLUGIN_VERSION}" + ) + +EmbedResources( + ${EMBEDDED_RESOURCES} + ) + +if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR + ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR + ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") + link_libraries(rt) +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + SET(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lws2_32") + + execute_process( + COMMAND + ${PYTHON_EXECUTABLE} ${ORTHANC_FRAMEWORK_ROOT}/../Resources/WindowsResources.py + ${ORTHANC_PLUGIN_VERSION} "OrthancSkeleton" OrthancSkeleton.dll "Skeleton plugin for Orthanc" + ERROR_VARIABLE Failure + OUTPUT_FILE ${AUTOGENERATED_DIR}/Version.rc + ) + + if (Failure) + message(FATAL_ERROR "Error while computing the version information: ${Failure}") + endif() + + list(APPEND AUTOGENERATED_SOURCES ${AUTOGENERATED_DIR}/Version.rc) +endif() + + +add_custom_target( + AutogeneratedTarget + DEPENDS + ${AUTOGENERATED_SOURCES} + ) + +add_library(OrthancSkeleton + SHARED + ${AUTOGENERATED_SOURCES} + ${ORTHANC_CORE_SOURCES} + ${ORTHANC_PLUGINS_SOURCES} + + # Your source files + ${CMAKE_SOURCE_DIR}/Plugin.cpp + ) + +add_dependencies(OrthancSkeleton AutogeneratedTarget) + + +set_target_properties(OrthancSkeleton PROPERTIES + VERSION ${ORTHANC_PLUGIN_VERSION} + SOVERSION ${ORTHANC_PLUGIN_VERSION}) + +install( + TARGETS OrthancSkeleton + RUNTIME DESTINATION lib # Destination for Windows + LIBRARY DESTINATION share/orthanc/plugins # Destination for Linux + ) + +if (COMMAND DefineSourceBasenameForTarget) + DefineSourceBasenameForTarget(OrthancSkeleton) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Samples/CppSkeleton/EmbeddedResources/app.js Tue May 20 09:48:38 2025 +0200 @@ -0,0 +1,1 @@ +console.log('Hello, world!');
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Samples/CppSkeleton/NOTES.txt Tue May 20 09:48:38 2025 +0200 @@ -0,0 +1,43 @@ + +Content +======= + +This folder contains a sample, minimal C++ plugin for Orthanc that +supports multiple target architectures. This skeleton also illustrates +how to properly include the Orthanc Framework and how to use embedded +resources. + + +Build instructions +================== + +To compile for developers: + +$ mkdir Build +$ cd Build +$ cmake .. \ + -DORTHANC_FRAMEWORK_ROOT=${PWD}/../../../../../OrthancFramework/Sources \ + -DORTHANC_FRAMEWORK_SOURCE=path \ + -DUSE_SYSTEM_ORTHANC_SDK=OFF +$ make -j4 + + +Shipping to users +================= + +If shipping the plugin to users (i.e., non-developers), you would have +to prepare your project by typing: + +$ ./Resources/SyncOrthancFolder.py + +The resulting content of the "./Resources/Orthanc/" must be included +in your project. + +Evidently, do not forget to adapt the values in "CMakeLists.txt" + +The users would then use the following build instructions: + +$ mkdir Build +$ cd Build +$ cmake .. -DALLOW_DOWNLOADS=ON -DUSE_SYSTEM_ORTHANC_SDK=OFF +$ make -j4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Samples/CppSkeleton/Plugin.cpp Tue May 20 09:48:38 2025 +0200 @@ -0,0 +1,121 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include <Logging.h> +#include <OrthancPluginCppWrapper.h> + +#if ORTHANC_STANDALONE == 1 +# include <EmbeddedResources.h> +#else +# include <SystemToolbox.h> +#endif + + +static void GetEmbeddedResource(std::string& target, + const std::string& path) +{ +#if ORTHANC_STANDALONE == 0 + Orthanc::SystemToolbox::ReadFile(target, Orthanc::SystemToolbox::InterpretRelativePath(PLUGIN_RESOURCES_PATH, path)); +#else + const std::string s = "/" + path; + Orthanc::EmbeddedResources::GetDirectoryResource(target, Orthanc::EmbeddedResources::PLUGIN_RESOURCES, s.c_str()); +#endif +} + + +static bool DisplayPerformanceWarning() +{ + (void) DisplayPerformanceWarning; // Disable warning about unused function + LOG(WARNING) << "Performance warning in plugin: " + << "Non-release build, runtime debug assertions are turned on"; + return true; +} + + +extern "C" +{ + ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) + { + OrthancPlugins::SetGlobalContext(context, ORTHANC_PLUGIN_NAME); + +#if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4) + Orthanc::Logging::InitializePluginContext(context, ORTHANC_PLUGIN_NAME); +#elif ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 7, 2) + Orthanc::Logging::InitializePluginContext(context); +#else + Orthanc::Logging::Initialize(context); +#endif + + assert(DisplayPerformanceWarning()); + + Orthanc::Logging::EnableInfoLevel(true); + + /* Check the version of the Orthanc core */ + if (OrthancPluginCheckVersion(context) == 0) + { + char info[1024]; + sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", + context->orthancVersion, + ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); + OrthancPluginLogError(context, info); + return -1; + } + + OrthancPlugins::SetDescription(ORTHANC_PLUGIN_NAME, "Skeleton of a C++ plugin Orthanc."); + + try + { + std::string s; + GetEmbeddedResource(s, "app.js"); + LOG(WARNING) << s; + } + catch (Orthanc::OrthancException& e) + { + LOG(ERROR) << "Exception while initializing the plugin: " << e.What(); + return -1; + } + + return 0; + } + + + ORTHANC_PLUGINS_API void OrthancPluginFinalize() + { + LOG(WARNING) << "Finalizing the skeleton plugin"; + Orthanc::Logging::Finalize(); + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetName() + { + return ORTHANC_PLUGIN_NAME; + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() + { + return ORTHANC_PLUGIN_VERSION; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Samples/CppSkeleton/Resources/SyncOrthancFolder.py Tue May 20 09:48:38 2025 +0200 @@ -0,0 +1,103 @@ +#!/usr/bin/python3 + +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2025 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +# +# This maintenance script updates the content of the "Orthanc" folder +# to match the latest version of the Orthanc source code. +# + +import multiprocessing +import os +import stat +import urllib.request + +TARGET = os.path.join(os.path.dirname(__file__), 'Orthanc') +PLUGIN_SDK_VERSION = '1.0.0' +REPOSITORY = 'https://orthanc.uclouvain.be/hg/%s/raw-file' + +FILES = [ + ('orthanc', 'OrthancFramework/Resources/CMake/AutoGeneratedCode.cmake', 'CMake'), + ('orthanc', 'OrthancFramework/Resources/CMake/Compiler.cmake', 'CMake'), + ('orthanc', 'OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake', 'CMake'), + ('orthanc', 'OrthancFramework/Resources/CMake/DownloadPackage.cmake', 'CMake'), + ('orthanc', 'OrthancFramework/Resources/EmbedResources.py', 'CMake'), + + ('orthanc', 'OrthancFramework/Resources/Toolchains/LinuxStandardBaseToolchain.cmake', 'Toolchains'), + ('orthanc', 'OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain32.cmake', 'Toolchains'), + ('orthanc', 'OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain64.cmake', 'Toolchains'), + ('orthanc', 'OrthancFramework/Resources/Toolchains/MinGWToolchain.cmake', 'Toolchains'), + + ('orthanc', 'OrthancServer/Plugins/Samples/Common/ExportedSymbolsPlugins.list', 'Plugins'), + ('orthanc', 'OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp', 'Plugins'), + ('orthanc', 'OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h', 'Plugins'), + ('orthanc', 'OrthancServer/Plugins/Samples/Common/OrthancPluginException.h', 'Plugins'), + ('orthanc', 'OrthancServer/Plugins/Samples/Common/OrthancPluginsExports.cmake', 'Plugins'), + ('orthanc', 'OrthancServer/Plugins/Samples/Common/VersionScriptPlugins.map', 'Plugins'), +] + +SDK = [ + 'orthanc/OrthancCPlugin.h', +] + + +def Download(x): + repository = x[0] + branch = x[1] + source = x[2] + target = os.path.join(TARGET, x[3]) + print(target) + + try: + os.makedirs(os.path.dirname(target)) + except: + pass + + url = '%s/%s/%s' % (REPOSITORY % repository, branch, source) + + with open(target, 'wb') as f: + try: + f.write(urllib.request.urlopen(url).read()) + except: + print('ERROR: %s' % url) + raise + + +commands = [] + +for f in FILES: + commands.append([ f[0], + 'default', + f[1], + os.path.join(f[2], os.path.basename(f[1])) ]) + +for f in SDK: + commands.append([ + 'orthanc', + 'Orthanc-%s' % PLUGIN_SDK_VERSION, + 'Plugins/Include/%s' % f, + 'Sdk-%s/%s' % (PLUGIN_SDK_VERSION, f) + ]) + + +pool = multiprocessing.Pool(10) # simultaneous downloads +pool.map(Download, commands)