Mercurial > hg > orthanc-python
changeset 63:32de70a1e4c7
New functions from the SDK wrapped in Python: CreateDicom, RegisterFindCallback, RegisterMoveCallback
line wrap: on
line diff
--- a/CMakeLists.txt Fri May 28 10:53:18 2021 +0200 +++ b/CMakeLists.txt Thu Jun 10 18:19:27 2021 +0200 @@ -159,6 +159,7 @@ add_library(OrthancPython SHARED Sources/Autogenerated/sdk.cpp + Sources/DicomScpCallbacks.cpp Sources/IncomingHttpRequestFilter.cpp Sources/OnChangeCallback.cpp Sources/OnStoredInstanceCallback.cpp @@ -169,6 +170,7 @@ Sources/PythonObject.cpp Sources/PythonString.cpp Sources/RestCallbacks.cpp + Sources/ICallbackRegistration.cpp # Third-party sources ${CMAKE_SOURCE_DIR}/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp
--- a/CodeAnalysis/Class.mustache Fri May 28 10:53:18 2021 +0200 +++ b/CodeAnalysis/Class.mustache Thu Jun 10 18:19:27 2021 +0200 @@ -17,22 +17,20 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - {{class_name}}* object_; - bool borrowed_; -} sdk_{{class_name}}_Object; - - - -// Forward declaration of the methods +// Forward declaration of the autogenerated methods {{#methods}} static PyObject *sdk_{{class_name}}_{{c_function}}( sdk_{{class_name}}_Object* self, PyObject *args); {{/methods}} +// End of forward declarations + + +// Forward declaration of the custom methods +{{#custom_methods}} +extern PyObject *{{implementation}}( + sdk_{{class_name}}_Object* self, PyObject *args); +{{/custom_methods}} +// End of forward declarations static PyMethodDef sdk_{{class_name}}_Methods[] = { @@ -41,6 +39,11 @@ (PyCFunction) sdk_{{class_name}}_{{c_function}}, METH_VARARGS, "Generated from C function {{c_function}}()" }, {{/methods}} +{{#custom_methods}} + { "{{method_name}}", + (PyCFunction) {{implementation}}, METH_VARARGS, + "Generated from C function {{sdk_function}}()" }, +{{/custom_methods}} { NULL } /* Sentinel */ }; @@ -157,7 +160,7 @@ } -PyObject* Get{{class_name}}Type() +PyTypeObject* Get{{class_name}}Type() { - return (PyObject*) &sdk_{{class_name}}_Type; + return &sdk_{{class_name}}_Type; }
--- a/CodeAnalysis/ParseOrthancSDK.py Fri May 28 10:53:18 2021 +0200 +++ b/CodeAnalysis/ParseOrthancSDK.py Thu Jun 10 18:19:27 2021 +0200 @@ -31,6 +31,42 @@ ## +## Configuration of the custom primitives that are manually +## implemented (not autogenerated) +## + +CUSTOM_FUNCTIONS = { + 'OrthancPluginCreateDicom', + 'OrthancPluginFreeMemoryBuffer', + 'OrthancPluginFreeString', + 'OrthancPluginGetFindQueryTag', + 'OrthancPluginRegisterFindCallback', + 'OrthancPluginRegisterIncomingHttpRequestFilter', # Implemented through v2 + 'OrthancPluginRegisterIncomingHttpRequestFilter2', + 'OrthancPluginRegisterMoveCallback', + 'OrthancPluginRegisterOnChangeCallback', + 'OrthancPluginRegisterOnStoredInstanceCallback', + 'OrthancPluginRegisterRestCallback', # Implemented using OrthancPlugins::RegisterRestCallback + 'OrthancPluginRegisterRestCallbackNoLock', # Implemented using OrthancPlugins::RegisterRestCallback +} + +CUSTOM_METHODS = [ + { + 'class_name' : 'OrthancPluginFindQuery', + 'method_name' : 'GetFindQueryTagGroup', + 'implementation' : 'GetFindQueryTagGroup', + 'sdk_function' : 'OrthancPluginGetFindQueryTag', + }, + { + 'class_name' : 'OrthancPluginFindQuery', + 'method_name' : 'GetFindQueryTagElement', + 'implementation' : 'GetFindQueryTagElement', + 'sdk_function' : 'OrthancPluginGetFindQueryTag', + }, +] + + +## ## Parse the command-line arguments ## @@ -40,7 +76,7 @@ help = 'manually provides the path to the libclang shared library') parser.add_argument('--source', default = os.path.join(os.path.dirname(__file__), - '../Resources/Orthanc/Sdk-1.5.7/orthanc/OrthancCPlugin.h'), + '../Resources/Orthanc/Sdk-1.8.1/orthanc/OrthancCPlugin.h'), help = 'Input C++ file') parser.add_argument('--target', default = os.path.join(os.path.dirname(__file__), @@ -383,11 +419,13 @@ CheckOnlySupportedArguments(args[1:])): className = args[0].type.get_pointee().spelling + print('Simple method of class %s: %s' % (className, node.spelling)) + if node.spelling in CUSTOM_FUNCTIONS: + raise Exception('Cannot overwrite an autogenerated method: %s()' % node.spelling) + if className.startswith('const '): className = className[len('const '):] - print('Simple method of class %s: %s' % (className, node.spelling)) - method = GenerateFunctionBodyTemplate(node.spelling, node.result_type, args[1:]) method['self'] = ', self->object_' classes[className]['methods'].append(method) @@ -397,12 +435,12 @@ IsTargetMemoryBufferType(args[0].type) and IsClassType(args[1].type) and CheckOnlySupportedArguments(args[2:])): - print('Simple method of class %s, returning bytes: %s' % ( - args[1].type.get_pointee().spelling, - node.spelling)) - className = args[1].type.get_pointee().spelling + print('Simple method of class %s, returning bytes: %s' % (className, node.spelling)) + if node.spelling in CUSTOM_FUNCTIONS: + raise Exception('Cannot overwrite an autogenerated method: %s()' % node.spelling) + if className.startswith('const '): className = className[len('const '):] @@ -410,6 +448,10 @@ method['self'] = ', self->object_' classes[className]['methods'].append(method) countSupportedFunctions += 1 + + elif node.spelling in CUSTOM_FUNCTIONS: + print('Ignoring custom function that is manually implemented: %s()' % node.spelling) + countSupportedFunctions += 1 else: print('*** UNSUPPORTED INPUT: %s' % node.spelling) @@ -424,7 +466,8 @@ classes[name] = { 'class_name' : name, 'short_name' : name[len('OrthancPlugin'):], - 'methods' : [ ] + 'methods' : [ ], + 'custom_methods' : [ ], } @@ -443,6 +486,9 @@ with open(os.path.join(ROOT, 'Class.mustache'), 'r') as f: template = f.read() + for method in CUSTOM_METHODS: + classes[method['class_name']]['custom_methods'].append(method) + for (key, value) in classes.items(): with open(os.path.join(TARGET, 'sdk_%s.impl.h' % value['class_name']), 'w') as h: h.write(renderer.render(template, value))
--- a/CodeAnalysis/sdk.h.mustache Fri May 28 10:53:18 2021 +0200 +++ b/CodeAnalysis/sdk.h.mustache Thu Jun 10 18:19:27 2021 +0200 @@ -25,5 +25,19 @@ PyMethodDef* GetOrthancSdkFunctions(); {{#classes}} -PyObject* Get{{class_name}}Type(); +PyTypeObject* Get{{class_name}}Type(); {{/classes}} + +#include <orthanc/OrthancCPlugin.h> + +{{#classes}} +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + {{class_name}}* object_; + bool borrowed_; +} sdk_{{class_name}}_Object; + +{{/classes}}
--- a/NEWS Fri May 28 10:53:18 2021 +0200 +++ b/NEWS Thu Jun 10 18:19:27 2021 +0200 @@ -1,6 +1,13 @@ Pending changes in the mainline =============================== +* New functions from the SDK wrapped in Python: + - orthanc.CreateDicom() + - orthanc.RegisterFindCallback() + - orthanc.RegisterMoveCallback() + - orthanc.FindQuery.GetFindQueryTagGroup() + - orthanc.FindQuery.GetFindQueryTagElement() + Version 3.1 (2021-01-22) ========================
--- a/Sources/Autogenerated/sdk.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk.h Thu Jun 10 18:19:27 2021 +0200 @@ -24,16 +24,136 @@ void RegisterOrthancSdk(PyObject* module); PyMethodDef* GetOrthancSdkFunctions(); -PyObject* GetOrthancPluginRestOutputType(); -PyObject* GetOrthancPluginServerChunkedRequestReaderType(); -PyObject* GetOrthancPluginImageType(); -PyObject* GetOrthancPluginJobType(); -PyObject* GetOrthancPluginWorklistQueryType(); -PyObject* GetOrthancPluginStorageAreaType(); -PyObject* GetOrthancPluginFindMatcherType(); -PyObject* GetOrthancPluginDicomWebNodeType(); -PyObject* GetOrthancPluginWorklistAnswersType(); -PyObject* GetOrthancPluginFindAnswersType(); -PyObject* GetOrthancPluginPeersType(); -PyObject* GetOrthancPluginDicomInstanceType(); -PyObject* GetOrthancPluginFindQueryType(); +PyTypeObject* GetOrthancPluginRestOutputType(); +PyTypeObject* GetOrthancPluginServerChunkedRequestReaderType(); +PyTypeObject* GetOrthancPluginImageType(); +PyTypeObject* GetOrthancPluginJobType(); +PyTypeObject* GetOrthancPluginWorklistQueryType(); +PyTypeObject* GetOrthancPluginStorageAreaType(); +PyTypeObject* GetOrthancPluginFindMatcherType(); +PyTypeObject* GetOrthancPluginDicomWebNodeType(); +PyTypeObject* GetOrthancPluginWorklistAnswersType(); +PyTypeObject* GetOrthancPluginFindAnswersType(); +PyTypeObject* GetOrthancPluginPeersType(); +PyTypeObject* GetOrthancPluginDicomInstanceType(); +PyTypeObject* GetOrthancPluginFindQueryType(); + +#include <orthanc/OrthancCPlugin.h> + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginRestOutput* object_; + bool borrowed_; +} sdk_OrthancPluginRestOutput_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginServerChunkedRequestReader* object_; + bool borrowed_; +} sdk_OrthancPluginServerChunkedRequestReader_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginImage* object_; + bool borrowed_; +} sdk_OrthancPluginImage_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginJob* object_; + bool borrowed_; +} sdk_OrthancPluginJob_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginWorklistQuery* object_; + bool borrowed_; +} sdk_OrthancPluginWorklistQuery_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginStorageArea* object_; + bool borrowed_; +} sdk_OrthancPluginStorageArea_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginFindMatcher* object_; + bool borrowed_; +} sdk_OrthancPluginFindMatcher_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginDicomWebNode* object_; + bool borrowed_; +} sdk_OrthancPluginDicomWebNode_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginWorklistAnswers* object_; + bool borrowed_; +} sdk_OrthancPluginWorklistAnswers_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginFindAnswers* object_; + bool borrowed_; +} sdk_OrthancPluginFindAnswers_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginPeers* object_; + bool borrowed_; +} sdk_OrthancPluginPeers_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginDicomInstance* object_; + bool borrowed_; +} sdk_OrthancPluginDicomInstance_Object; + +typedef struct +{ + PyObject_HEAD + + /* Type-specific fields go here. */ + OrthancPluginFindQuery* object_; + bool borrowed_; +} sdk_OrthancPluginFindQuery_Object; +
--- a/Sources/Autogenerated/sdk_OrthancPluginDicomInstance.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginDicomInstance.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,18 +17,7 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginDicomInstance* object_; - bool borrowed_; -} sdk_OrthancPluginDicomInstance_Object; - - - -// Forward declaration of the methods +// Forward declaration of the autogenerated methods static PyObject *sdk_OrthancPluginDicomInstance_OrthancPluginGetInstanceRemoteAet( sdk_OrthancPluginDicomInstance_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginDicomInstance_OrthancPluginGetInstanceSize( @@ -57,6 +46,11 @@ sdk_OrthancPluginDicomInstance_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginDicomInstance_OrthancPluginGetInstanceAdvancedJson( sdk_OrthancPluginDicomInstance_Object* self, PyObject *args); +// End of forward declarations + + +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginDicomInstance_Methods[] = { @@ -595,7 +589,7 @@ } -PyObject* GetOrthancPluginDicomInstanceType() +PyTypeObject* GetOrthancPluginDicomInstanceType() { - return (PyObject*) &sdk_OrthancPluginDicomInstance_Type; + return &sdk_OrthancPluginDicomInstance_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginDicomWebNode.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginDicomWebNode.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,18 +17,12 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginDicomWebNode* object_; - bool borrowed_; -} sdk_OrthancPluginDicomWebNode_Object; +// Forward declaration of the autogenerated methods +// End of forward declarations - -// Forward declaration of the methods +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginDicomWebNode_Methods[] = { @@ -103,7 +97,7 @@ } -PyObject* GetOrthancPluginDicomWebNodeType() +PyTypeObject* GetOrthancPluginDicomWebNodeType() { - return (PyObject*) &sdk_OrthancPluginDicomWebNode_Type; + return &sdk_OrthancPluginDicomWebNode_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginFindAnswers.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginFindAnswers.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,22 +17,16 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginFindAnswers* object_; - bool borrowed_; -} sdk_OrthancPluginFindAnswers_Object; - - - -// Forward declaration of the methods +// Forward declaration of the autogenerated methods static PyObject *sdk_OrthancPluginFindAnswers_OrthancPluginFindAddAnswer( sdk_OrthancPluginFindAnswers_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginFindAnswers_OrthancPluginFindMarkIncomplete( sdk_OrthancPluginFindAnswers_Object* self, PyObject *args); +// End of forward declarations + + +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginFindAnswers_Methods[] = { @@ -182,7 +176,7 @@ } -PyObject* GetOrthancPluginFindAnswersType() +PyTypeObject* GetOrthancPluginFindAnswersType() { - return (PyObject*) &sdk_OrthancPluginFindAnswers_Type; + return &sdk_OrthancPluginFindAnswers_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginFindMatcher.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginFindMatcher.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,20 +17,14 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginFindMatcher* object_; - bool borrowed_; -} sdk_OrthancPluginFindMatcher_Object; +// Forward declaration of the autogenerated methods +static PyObject *sdk_OrthancPluginFindMatcher_OrthancPluginFindMatcherIsMatch( + sdk_OrthancPluginFindMatcher_Object* self, PyObject *args); +// End of forward declarations - -// Forward declaration of the methods -static PyObject *sdk_OrthancPluginFindMatcher_OrthancPluginFindMatcherIsMatch( - sdk_OrthancPluginFindMatcher_Object* self, PyObject *args); +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginFindMatcher_Methods[] = { @@ -157,7 +151,7 @@ } -PyObject* GetOrthancPluginFindMatcherType() +PyTypeObject* GetOrthancPluginFindMatcherType() { - return (PyObject*) &sdk_OrthancPluginFindMatcher_Type; + return &sdk_OrthancPluginFindMatcher_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginFindQuery.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginFindQuery.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,24 +17,22 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginFindQuery* object_; - bool borrowed_; -} sdk_OrthancPluginFindQuery_Object; - - - -// Forward declaration of the methods +// Forward declaration of the autogenerated methods static PyObject *sdk_OrthancPluginFindQuery_OrthancPluginGetFindQuerySize( sdk_OrthancPluginFindQuery_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginFindQuery_OrthancPluginGetFindQueryTagName( sdk_OrthancPluginFindQuery_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginFindQuery_OrthancPluginGetFindQueryValue( sdk_OrthancPluginFindQuery_Object* self, PyObject *args); +// End of forward declarations + + +// Forward declaration of the custom methods +extern PyObject *GetFindQueryTagGroup( + sdk_OrthancPluginFindQuery_Object* self, PyObject *args); +extern PyObject *GetFindQueryTagElement( + sdk_OrthancPluginFindQuery_Object* self, PyObject *args); +// End of forward declarations static PyMethodDef sdk_OrthancPluginFindQuery_Methods[] = { @@ -47,6 +45,12 @@ { "GetFindQueryValue", (PyCFunction) sdk_OrthancPluginFindQuery_OrthancPluginGetFindQueryValue, METH_VARARGS, "Generated from C function OrthancPluginGetFindQueryValue()" }, + { "GetFindQueryTagGroup", + (PyCFunction) GetFindQueryTagGroup, METH_VARARGS, + "Generated from C function OrthancPluginGetFindQueryTag()" }, + { "GetFindQueryTagElement", + (PyCFunction) GetFindQueryTagElement, METH_VARARGS, + "Generated from C function OrthancPluginGetFindQueryTag()" }, { NULL } /* Sentinel */ }; @@ -211,7 +215,7 @@ } -PyObject* GetOrthancPluginFindQueryType() +PyTypeObject* GetOrthancPluginFindQueryType() { - return (PyObject*) &sdk_OrthancPluginFindQuery_Type; + return &sdk_OrthancPluginFindQuery_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginImage.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginImage.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,18 +17,7 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginImage* object_; - bool borrowed_; -} sdk_OrthancPluginImage_Object; - - - -// Forward declaration of the methods +// Forward declaration of the autogenerated methods static PyObject *sdk_OrthancPluginImage_OrthancPluginGetImagePixelFormat( sdk_OrthancPluginImage_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginImage_OrthancPluginGetImageWidth( @@ -41,6 +30,11 @@ sdk_OrthancPluginImage_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginImage_OrthancPluginDrawText( sdk_OrthancPluginImage_Object* self, PyObject *args); +// End of forward declarations + + +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginImage_Methods[] = { @@ -316,7 +310,7 @@ } -PyObject* GetOrthancPluginImageType() +PyTypeObject* GetOrthancPluginImageType() { - return (PyObject*) &sdk_OrthancPluginImage_Type; + return &sdk_OrthancPluginImage_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginJob.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginJob.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,20 +17,14 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginJob* object_; - bool borrowed_; -} sdk_OrthancPluginJob_Object; +// Forward declaration of the autogenerated methods +static PyObject *sdk_OrthancPluginJob_OrthancPluginSubmitJob( + sdk_OrthancPluginJob_Object* self, PyObject *args); +// End of forward declarations - -// Forward declaration of the methods -static PyObject *sdk_OrthancPluginJob_OrthancPluginSubmitJob( - sdk_OrthancPluginJob_Object* self, PyObject *args); +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginJob_Methods[] = { @@ -168,7 +162,7 @@ } -PyObject* GetOrthancPluginJobType() +PyTypeObject* GetOrthancPluginJobType() { - return (PyObject*) &sdk_OrthancPluginJob_Type; + return &sdk_OrthancPluginJob_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginPeers.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginPeers.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,18 +17,7 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginPeers* object_; - bool borrowed_; -} sdk_OrthancPluginPeers_Object; - - - -// Forward declaration of the methods +// Forward declaration of the autogenerated methods static PyObject *sdk_OrthancPluginPeers_OrthancPluginGetPeersCount( sdk_OrthancPluginPeers_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginPeers_OrthancPluginGetPeerName( @@ -37,6 +26,11 @@ sdk_OrthancPluginPeers_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginPeers_OrthancPluginGetPeerUserProperty( sdk_OrthancPluginPeers_Object* self, PyObject *args); +// End of forward declarations + + +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginPeers_Methods[] = { @@ -268,7 +262,7 @@ } -PyObject* GetOrthancPluginPeersType() +PyTypeObject* GetOrthancPluginPeersType() { - return (PyObject*) &sdk_OrthancPluginPeers_Type; + return &sdk_OrthancPluginPeers_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginRestOutput.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginRestOutput.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,18 +17,7 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginRestOutput* object_; - bool borrowed_; -} sdk_OrthancPluginRestOutput_Object; - - - -// Forward declaration of the methods +// Forward declaration of the autogenerated methods static PyObject *sdk_OrthancPluginRestOutput_OrthancPluginAnswerBuffer( sdk_OrthancPluginRestOutput_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginRestOutput_OrthancPluginCompressAndAnswerPngImage( @@ -55,6 +44,11 @@ sdk_OrthancPluginRestOutput_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginRestOutput_OrthancPluginSetHttpErrorDetails( sdk_OrthancPluginRestOutput_Object* self, PyObject *args); +// End of forward declarations + + +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginRestOutput_Methods[] = { @@ -568,7 +562,7 @@ } -PyObject* GetOrthancPluginRestOutputType() +PyTypeObject* GetOrthancPluginRestOutputType() { - return (PyObject*) &sdk_OrthancPluginRestOutput_Type; + return &sdk_OrthancPluginRestOutput_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginServerChunkedRequestReader.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginServerChunkedRequestReader.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,18 +17,12 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginServerChunkedRequestReader* object_; - bool borrowed_; -} sdk_OrthancPluginServerChunkedRequestReader_Object; +// Forward declaration of the autogenerated methods +// End of forward declarations - -// Forward declaration of the methods +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginServerChunkedRequestReader_Methods[] = { @@ -103,7 +97,7 @@ } -PyObject* GetOrthancPluginServerChunkedRequestReaderType() +PyTypeObject* GetOrthancPluginServerChunkedRequestReaderType() { - return (PyObject*) &sdk_OrthancPluginServerChunkedRequestReader_Type; + return &sdk_OrthancPluginServerChunkedRequestReader_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginStorageArea.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginStorageArea.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,18 +17,7 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginStorageArea* object_; - bool borrowed_; -} sdk_OrthancPluginStorageArea_Object; - - - -// Forward declaration of the methods +// Forward declaration of the autogenerated methods static PyObject *sdk_OrthancPluginStorageArea_OrthancPluginStorageAreaCreate( sdk_OrthancPluginStorageArea_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginStorageArea_OrthancPluginStorageAreaRead( @@ -37,6 +26,11 @@ sdk_OrthancPluginStorageArea_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginStorageArea_OrthancPluginReconstructMainDicomTags( sdk_OrthancPluginStorageArea_Object* self, PyObject *args); +// End of forward declarations + + +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginStorageArea_Methods[] = { @@ -279,7 +273,7 @@ } -PyObject* GetOrthancPluginStorageAreaType() +PyTypeObject* GetOrthancPluginStorageAreaType() { - return (PyObject*) &sdk_OrthancPluginStorageArea_Type; + return &sdk_OrthancPluginStorageArea_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginWorklistAnswers.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginWorklistAnswers.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,20 +17,14 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginWorklistAnswers* object_; - bool borrowed_; -} sdk_OrthancPluginWorklistAnswers_Object; +// Forward declaration of the autogenerated methods +static PyObject *sdk_OrthancPluginWorklistAnswers_OrthancPluginWorklistMarkIncomplete( + sdk_OrthancPluginWorklistAnswers_Object* self, PyObject *args); +// End of forward declarations - -// Forward declaration of the methods -static PyObject *sdk_OrthancPluginWorklistAnswers_OrthancPluginWorklistMarkIncomplete( - sdk_OrthancPluginWorklistAnswers_Object* self, PyObject *args); +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginWorklistAnswers_Methods[] = { @@ -139,7 +133,7 @@ } -PyObject* GetOrthancPluginWorklistAnswersType() +PyTypeObject* GetOrthancPluginWorklistAnswersType() { - return (PyObject*) &sdk_OrthancPluginWorklistAnswers_Type; + return &sdk_OrthancPluginWorklistAnswers_Type; }
--- a/Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.impl.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.impl.h Thu Jun 10 18:19:27 2021 +0200 @@ -17,22 +17,16 @@ **/ -typedef struct -{ - PyObject_HEAD - - /* Type-specific fields go here. */ - OrthancPluginWorklistQuery* object_; - bool borrowed_; -} sdk_OrthancPluginWorklistQuery_Object; - - - -// Forward declaration of the methods +// Forward declaration of the autogenerated methods static PyObject *sdk_OrthancPluginWorklistQuery_OrthancPluginWorklistIsMatch( sdk_OrthancPluginWorklistQuery_Object* self, PyObject *args); static PyObject *sdk_OrthancPluginWorklistQuery_OrthancPluginWorklistGetDicomQuery( sdk_OrthancPluginWorklistQuery_Object* self, PyObject *args); +// End of forward declarations + + +// Forward declaration of the custom methods +// End of forward declarations static PyMethodDef sdk_OrthancPluginWorklistQuery_Methods[] = { @@ -169,7 +163,7 @@ } -PyObject* GetOrthancPluginWorklistQueryType() +PyTypeObject* GetOrthancPluginWorklistQueryType() { - return (PyObject*) &sdk_OrthancPluginWorklistQuery_Type; + return &sdk_OrthancPluginWorklistQuery_Type; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sources/DicomScpCallbacks.cpp Thu Jun 10 18:19:27 2021 +0200 @@ -0,0 +1,396 @@ +/** + * Python plugin for Orthanc + * Copyright (C) 2020-2021 Osimis S.A., 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 "DicomScpCallbacks.h" + +#include "../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h" +#include "Autogenerated/sdk.h" +#include "ICallbackRegistration.h" +#include "PythonString.h" + + +static PyObject* findScpCallback_ = NULL; +static PyObject* moveScpCallback_ = NULL; + + +static PyObject *GetFindQueryTag(sdk_OrthancPluginFindQuery_Object* self, + PyObject *args, + bool isGroup) +{ + unsigned long index; + uint16_t group, element; + + if (self->object_ == NULL) + { + PyErr_SetString(PyExc_ValueError, "Invalid object"); + return NULL; + } + else if (!PyArg_ParseTuple(args, "k", &index)) + { + PyErr_SetString(PyExc_TypeError, "Index is missing"); + return NULL; + } + else if (OrthancPluginGetFindQueryTag(OrthancPlugins::GetGlobalContext(), &group, &element, self->object_, index) != + OrthancPluginErrorCode_Success) + { + PyErr_SetString(PyExc_ValueError, "Index is out of range"); + return NULL; + } + else if (isGroup) + { + return PyLong_FromUnsignedLong(group); + } + else + { + return PyLong_FromUnsignedLong(element); + } +} + + + +// Check out "CUSTOM_METHODS" in "../CodeAnalysis/ParseOrthancSDK.py" +PyObject *GetFindQueryTagGroup(sdk_OrthancPluginFindQuery_Object* self, PyObject *args) +{ + return GetFindQueryTag(self, args, true); +} + + +PyObject *GetFindQueryTagElement(sdk_OrthancPluginFindQuery_Object* self, PyObject *args) +{ + return GetFindQueryTag(self, args, false); +} + + +static OrthancPluginErrorCode FindCallback(OrthancPluginFindAnswers *answers, + const OrthancPluginFindQuery *query, + const char *issuerAet, + const char *calledAet) +{ + try + { + PythonLock lock; + + PyObject *pAnswers, *pQuery; + + { + PythonObject args(lock, PyTuple_New(2)); + PyTuple_SetItem(args.GetPyObject(), 0, PyLong_FromSsize_t((intptr_t) answers)); + PyTuple_SetItem(args.GetPyObject(), 1, PyBool_FromLong(true /* borrowed, don't destruct */)); + pAnswers = PyObject_CallObject((PyObject *) GetOrthancPluginFindAnswersType(), args.GetPyObject()); + } + + { + PythonObject args(lock, PyTuple_New(2)); + PyTuple_SetItem(args.GetPyObject(), 0, PyLong_FromSsize_t((intptr_t) query)); + PyTuple_SetItem(args.GetPyObject(), 1, PyBool_FromLong(true /* borrowed, don't destruct */)); + pQuery = PyObject_CallObject((PyObject *) GetOrthancPluginFindQueryType(), args.GetPyObject()); + } + + PythonString pIssuerAet(lock, issuerAet); + PythonString pCalledAet(lock, calledAet); + + { + PythonObject args(lock, PyTuple_New(4)); + PyTuple_SetItem(args.GetPyObject(), 0, pAnswers); + PyTuple_SetItem(args.GetPyObject(), 1, pQuery); + PyTuple_SetItem(args.GetPyObject(), 2, pIssuerAet.Release()); + PyTuple_SetItem(args.GetPyObject(), 3, pCalledAet.Release()); + + assert(findScpCallback_ != NULL); + PythonObject result(lock, PyObject_CallObject(findScpCallback_, args.GetPyObject())); + } + + return lock.CheckCallbackSuccess("Python C-FIND SCP callback"); + } + catch (OrthancPlugins::PluginException& e) + { + return e.GetErrorCode(); + } +} + + + +class IMoveDriver : public boost::noncopyable +{ +public: + virtual ~IMoveDriver() + { + } + + virtual void Apply() = 0; +}; + + +static void* CreateMoveCallback(OrthancPluginResourceType resourceType, + const char *patientId, + const char *accessionNumber, + const char *studyInstanceUid, + const char *seriesInstanceUid, + const char *sopInstanceUid, + const char *originatorAet, + const char *sourceAet, + const char *targetAet, + uint16_t originatorId) +{ + class Driver : public IMoveDriver + { + private: + OrthancPluginResourceType resourceType_; + std::string patientId_; + std::string accessionNumber_; + std::string studyInstanceUid_; + std::string seriesInstanceUid_; + std::string sopInstanceUid_; + std::string originatorAet_; + std::string sourceAet_; + std::string targetAet_; + uint16_t originatorId_; + + public: + Driver(OrthancPluginResourceType resourceType, + const char *patientId, + const char *accessionNumber, + const char *studyInstanceUid, + const char *seriesInstanceUid, + const char *sopInstanceUid, + const char *originatorAet, + const char *sourceAet, + const char *targetAet, + uint16_t originatorId) : + resourceType_(resourceType), + originatorId_(originatorId) + { + if (patientId != NULL) + { + patientId_.assign(patientId); + } + + if (accessionNumber != NULL) + { + accessionNumber_.assign(accessionNumber); + } + + if (studyInstanceUid != NULL) + { + studyInstanceUid_.assign(studyInstanceUid); + } + + if (seriesInstanceUid != NULL) + { + seriesInstanceUid_.assign(seriesInstanceUid); + } + + if (sopInstanceUid != NULL) + { + sopInstanceUid_.assign(sopInstanceUid); + } + + if (originatorAet != NULL) + { + originatorAet_.assign(originatorAet); + } + + if (sourceAet != NULL) + { + sourceAet_.assign(sourceAet); + } + + if (targetAet != NULL) + { + targetAet_.assign(targetAet); + } + } + + + virtual void Apply() ORTHANC_OVERRIDE + { + PythonLock lock; + + PythonObject kw(lock, PyDict_New()); + + std::string level; + switch (resourceType_) + { + case OrthancPluginResourceType_Patient: + level = "PATIENT"; + break; + + case OrthancPluginResourceType_Study: + level = "STUDY"; + break; + + case OrthancPluginResourceType_Series: + level = "SERIES"; + break; + + case OrthancPluginResourceType_Instance: + level = "INSTANCE"; + break; + + default: + throw OrthancPlugins::PluginException(OrthancPluginErrorCode_ParameterOutOfRange); + } + + { + PythonString tmp(lock, level); + PyDict_SetItemString(kw.GetPyObject(), "Level", tmp.Release()); + } + + { + PythonString tmp(lock, patientId_); + PyDict_SetItemString(kw.GetPyObject(), "PatientID", tmp.Release()); + } + + { + PythonString tmp(lock, accessionNumber_); + PyDict_SetItemString(kw.GetPyObject(), "AccessionNumber", tmp.Release()); + } + + { + PythonString tmp(lock, studyInstanceUid_); + PyDict_SetItemString(kw.GetPyObject(), "StudyInstanceUID", tmp.Release()); + } + + { + PythonString tmp(lock, seriesInstanceUid_); + PyDict_SetItemString(kw.GetPyObject(), "SeriesInstanceUID", tmp.Release()); + } + + { + PythonString tmp(lock, sopInstanceUid_); + PyDict_SetItemString(kw.GetPyObject(), "SOPInstanceUID", tmp.Release()); + } + + { + PythonString tmp(lock, originatorAet_); + PyDict_SetItemString(kw.GetPyObject(), "OriginatorAET", tmp.Release()); + } + + { + PythonString tmp(lock, sourceAet_); + PyDict_SetItemString(kw.GetPyObject(), "SourceAET", tmp.Release()); + } + + { + PythonString tmp(lock, targetAet_); + PyDict_SetItemString(kw.GetPyObject(), "TargetAET", tmp.Release()); + } + + PyDict_SetItemString(kw.GetPyObject(), "OriginatorID", PyLong_FromUnsignedLong(originatorId_)); + + PythonObject args(lock, PyTuple_New(0)); + + assert(moveScpCallback_ != NULL); + PythonObject result(lock, PyObject_Call(moveScpCallback_, args.GetPyObject(), kw.GetPyObject())); + + OrthancPluginErrorCode code = lock.CheckCallbackSuccess("Python C-MOVE SCP callback"); + if (code != OrthancPluginErrorCode_Success) + { + throw OrthancPlugins::PluginException(code); + } + } + }; + + try + { + return new Driver(resourceType, patientId, accessionNumber, studyInstanceUid, + seriesInstanceUid, sopInstanceUid, originatorAet, sourceAet, + targetAet, originatorId); + } + catch (OrthancPlugins::PluginException& e) + { + return NULL; + } +} + + +static uint32_t GetMoveSize(void *moveDriver) +{ + assert(moveDriver != NULL); + return 1; +} + + +OrthancPluginErrorCode ApplyMove(void *moveDriver) +{ + assert(moveDriver != NULL); + + try + { + reinterpret_cast<IMoveDriver*>(moveDriver)->Apply(); + return OrthancPluginErrorCode_Success; + } + catch (OrthancPlugins::PluginException& e) + { + return e.GetErrorCode(); + } +} + + +void FreeMove(void *moveDriver) +{ + assert(moveDriver != NULL); + delete reinterpret_cast<IMoveDriver*>(moveDriver); +} + + +PyObject* RegisterFindCallback(PyObject* module, PyObject* args) +{ + // The GIL is locked at this point (no need to create "PythonLock") + + class Registration : public ICallbackRegistration + { + public: + virtual void Register() ORTHANC_OVERRIDE + { + OrthancPluginRegisterFindCallback(OrthancPlugins::GetGlobalContext(), FindCallback); + } + }; + + Registration registration; + return ICallbackRegistration::Apply( + registration, args, findScpCallback_, "Python C-FIND SCP callback"); +} + + +PyObject* RegisterMoveCallback(PyObject* module, PyObject* args) +{ + // The GIL is locked at this point (no need to create "PythonLock") + + class Registration : public ICallbackRegistration + { + public: + virtual void Register() ORTHANC_OVERRIDE + { + OrthancPluginRegisterMoveCallback( + OrthancPlugins::GetGlobalContext(), CreateMoveCallback, GetMoveSize, ApplyMove, FreeMove); + } + }; + + Registration registration; + return ICallbackRegistration::Apply( + registration, args, moveScpCallback_, "Python C-MOVE SCP callback"); +} + + +void FinalizeDicomScpCallbacks() +{ + ICallbackRegistration::Unregister(findScpCallback_); + ICallbackRegistration::Unregister(moveScpCallback_); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sources/DicomScpCallbacks.h Thu Jun 10 18:19:27 2021 +0200 @@ -0,0 +1,28 @@ +/** + * Python plugin for Orthanc + * Copyright (C) 2020-2021 Osimis S.A., 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/>. + **/ + + +#pragma once + +#include "PythonHeaderWrapper.h" + +PyObject* RegisterFindCallback(PyObject* module, PyObject* args); + +PyObject* RegisterMoveCallback(PyObject* module, PyObject* args); + +void FinalizeDicomScpCallbacks();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sources/ICallbackRegistration.cpp Thu Jun 10 18:19:27 2021 +0200 @@ -0,0 +1,68 @@ +/** + * Python plugin for Orthanc + * Copyright (C) 2020-2021 Osimis S.A., 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 "ICallbackRegistration.h" + +#include "../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h" +#include "PythonLock.h" + +PyObject *ICallbackRegistration::Apply(ICallbackRegistration& registration, + PyObject* args, + PyObject*& singletonCallback, + const std::string& details) +{ + // https://docs.python.org/3/extending/extending.html#calling-python-functions-from-c + PyObject* callback = NULL; + + if (!PyArg_ParseTuple(args, "O", &callback) || + callback == NULL) + { + const std::string message = "Expected a callback function to register one " + details; + PyErr_SetString(PyExc_ValueError, message.c_str()); + return NULL; + } + else if (singletonCallback != NULL) + { + const std::string message = "Can only register one " + details; + PyErr_SetString(PyExc_RuntimeError, message.c_str()); + return NULL; + } + else + { + OrthancPlugins::LogInfo("Registering one " + details); + registration.Register(); + + singletonCallback = callback; + Py_XINCREF(singletonCallback); + + Py_INCREF(Py_None); + return Py_None; + } +} + + +void ICallbackRegistration::Unregister(PyObject*& singletonCallback) +{ + PythonLock lock; + + if (singletonCallback != NULL) + { + Py_XDECREF(singletonCallback); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sources/ICallbackRegistration.h Thu Jun 10 18:19:27 2021 +0200 @@ -0,0 +1,43 @@ +/** + * Python plugin for Orthanc + * Copyright (C) 2020-2021 Osimis S.A., 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/>. + **/ + + +#pragma once + +#include "PythonHeaderWrapper.h" + +#include <boost/noncopyable.hpp> +#include <string> + +class ICallbackRegistration : public boost::noncopyable +{ +public: + virtual ~ICallbackRegistration() + { + } + + virtual void Register() = 0; + + // The GIL must be locked + static PyObject *Apply(ICallbackRegistration& registration, + PyObject* args, + PyObject*& singletonCallback, + const std::string& details); + + static void Unregister(PyObject*& singletonCallback); +};
--- a/Sources/OnStoredInstanceCallback.cpp Fri May 28 10:53:18 2021 +0200 +++ b/Sources/OnStoredInstanceCallback.cpp Thu Jun 10 18:19:27 2021 +0200 @@ -43,7 +43,7 @@ PythonObject args(lock, PyTuple_New(2)); PyTuple_SetItem(args.GetPyObject(), 0, PyLong_FromSsize_t((intptr_t) instance)); PyTuple_SetItem(args.GetPyObject(), 1, PyBool_FromLong(true /* borrowed, don't destruct */)); - PyObject *pInst = PyObject_CallObject(GetOrthancPluginDicomInstanceType(), args.GetPyObject()); + PyObject *pInst = PyObject_CallObject((PyObject*) GetOrthancPluginDicomInstanceType(), args.GetPyObject()); /** * Construct the arguments tuple (output, uri)
--- a/Sources/Plugin.cpp Fri May 28 10:53:18 2021 +0200 +++ b/Sources/Plugin.cpp Thu Jun 10 18:19:27 2021 +0200 @@ -24,6 +24,7 @@ // https://fr.slideshare.net/YiLungTsai/embed-python +#include "DicomScpCallbacks.h" #include "IncomingHttpRequestFilter.h" #include "OnChangeCallback.h" #include "OnStoredInstanceCallback.h" @@ -51,6 +52,54 @@ +PyObject* CreateDicom(PyObject* module, PyObject* args) +{ + // The GIL is locked at this point (no need to create "PythonLock") + const char* json = NULL; + PyObject* pixelData = NULL; + long int flags = 0; + + if (!PyArg_ParseTuple(args, "sOl", &json, &pixelData, &flags)) + { + PyErr_SetString(PyExc_TypeError, "Please provide a JSON string, an orthanc.Image object, and a set of orthanc.CreateDicomFlags"); + return NULL; + } + else + { + OrthancPluginImage* image = NULL; + + if (pixelData == Py_None) + { + // No pixel data + } + else if (Py_TYPE(pixelData) == GetOrthancPluginImageType()) + { + image = reinterpret_cast<sdk_OrthancPluginImage_Object*>(pixelData)->object_; + } + else + { + PyErr_SetString(PyExc_TypeError, "Second parameter is not a valid orthanc.Image"); + return NULL; + } + + OrthancPlugins::MemoryBuffer buffer; + OrthancPluginErrorCode code = OrthancPluginCreateDicom(OrthancPlugins::GetGlobalContext(), *buffer, json, image, + static_cast<OrthancPluginCreateDicomFlags>(flags)); + + if (code == OrthancPluginErrorCode_Success) + { + return PyBytes_FromStringAndSize(buffer.GetData(), buffer.GetSize()); + } + else + { + PyErr_SetString(PyExc_ValueError, "Cannot create the DICOM instance"); + return NULL; + } + } +} + + + static bool pythonEnabled_ = false; static std::string userScriptName_; static std::vector<PyMethodDef> globalFunctions_; @@ -91,11 +140,36 @@ functions.push_back(f); } + + /** + * New in release 3.0 + **/ + { - // New in release 3.0 PyMethodDef f = { "RegisterIncomingHttpRequestFilter", RegisterIncomingHttpRequestFilter, METH_VARARGS, "" }; functions.push_back(f); } + + + /** + * New in release 3.1 + **/ + + { + PyMethodDef f = { "CreateDicom", CreateDicom, METH_VARARGS, "" }; + functions.push_back(f); + } + + { + PyMethodDef f = { "RegisterFindCallback", RegisterFindCallback, METH_VARARGS, "" }; + functions.push_back(f); + } + + { + PyMethodDef f = { "RegisterMoveCallback", RegisterMoveCallback, METH_VARARGS, "" }; + functions.push_back(f); + } + /** * Append all the global functions that were automatically generated @@ -298,6 +372,7 @@ FinalizeRestCallbacks(); FinalizeOnStoredInstanceCallback(); FinalizeIncomingHttpRequestFilter(); + FinalizeDicomScpCallbacks(); PythonLock::GlobalFinalize(); }
--- a/Sources/PythonLock.cpp Fri May 28 10:53:18 2021 +0200 +++ b/Sources/PythonLock.cpp Thu Jun 10 18:19:27 2021 +0200 @@ -291,6 +291,23 @@ +OrthancPluginErrorCode PythonLock::CheckCallbackSuccess(const std::string& callbackDetails) +{ + std::string traceback; + + if (HasErrorOccurred(traceback)) + { + OrthancPlugins::LogError("Error in the " + callbackDetails + ", traceback:\n" + traceback); + return OrthancPluginErrorCode_Plugin; + } + else + { + return OrthancPluginErrorCode_Success; + } +} + + + void PythonLock::GlobalInitialize(const std::string& moduleName, const std::string& exceptionName, ModuleFunctionsInstaller moduleFunctions,
--- a/Sources/PythonLock.h Fri May 28 10:53:18 2021 +0200 +++ b/Sources/PythonLock.h Thu Jun 10 18:19:27 2021 +0200 @@ -47,6 +47,8 @@ bool HasErrorOccurred(std::string& traceback); + OrthancPluginErrorCode CheckCallbackSuccess(const std::string& callbackDetails); + static void GlobalInitialize(const std::string& moduleName, const std::string& exceptionName, ModuleFunctionsInstaller moduleFunctions,
--- a/Sources/RestCallbacks.cpp Fri May 28 10:53:18 2021 +0200 +++ b/Sources/RestCallbacks.cpp Thu Jun 10 18:19:27 2021 +0200 @@ -84,7 +84,7 @@ PythonObject args(lock, PyTuple_New(2)); PyTuple_SetItem(args.GetPyObject(), 0, PyLong_FromSsize_t((intptr_t) output)); PyTuple_SetItem(args.GetPyObject(), 1, PyBool_FromLong(true /* borrowed, don't destruct */)); - PyObject *pInst = PyObject_CallObject(GetOrthancPluginRestOutputType(), args.GetPyObject()); + PyObject *pInst = PyObject_CallObject((PyObject*) GetOrthancPluginRestOutputType(), args.GetPyObject()); /**