# HG changeset patch # User Sebastien Jodogne # Date 1755006949 -7200 # Node ID 919836e3fafd769f7c66fbb49d0de75e4b23c98b # Parent a65ba8bd5784ba8b5c73491114d348ed3ee4036e manual wrapping of functions for key-value stores diff -r a65ba8bd5784 -r 919836e3fafd CodeAnalysis/CustomFunctions.json --- a/CodeAnalysis/CustomFunctions.json Tue Aug 12 13:50:34 2025 +0200 +++ b/CodeAnalysis/CustomFunctions.json Tue Aug 12 15:55:49 2025 +0200 @@ -377,6 +377,32 @@ { "comment" : "New in release 6.0", + "short_name" : "GetKeyValue", + "implementation" : "GetKeyValue", + "documentation" : { + "description" : [ "Get the value associated with a key in the Orthanc key-value store." ], + "args" : { + "storeId" : "The key-value store.", + "key" : "The key." + }, + "return" : "The value, or None." + }, + "args" : [ + { + "sdk_name" : "storeId", + "sdk_type" : "const char *" + }, + { + "sdk_name" : "key", + "sdk_type" : "const char *" + } + ], + "return_sdk_type" : "OrthancPluginMemoryBuffer *", + "since_sdk" : [ 1, 12, 8 ] + }, + + { + "comment" : "New in release 6.0", "short_name" : "SetStableStatus", "implementation" : "SetStableStatus", "documentation" : { diff -r a65ba8bd5784 -r 919836e3fafd CodeAnalysis/CustomMethods.json --- a/CodeAnalysis/CustomMethods.json Tue Aug 12 13:50:34 2025 +0200 +++ b/CodeAnalysis/CustomMethods.json Tue Aug 12 15:55:49 2025 +0200 @@ -65,5 +65,19 @@ ], "return_sdk_type" : "OrthancPluginMemoryBuffer *" } + ], + + "OrthancPluginKeysValuesIterator" : [ + { + "short_name" : "Next", + "implementation" : "KeysValuesIteratorNext", + "documentation" : { + "description" : [ "Advance to the next element in the iterator." ], + "return" : "Whether the iterator is done." + }, + "args" : [ + ], + "return_sdk_type" : "bool" + } ] } diff -r a65ba8bd5784 -r 919836e3fafd CodeAnalysis/GenerateOrthancSDK.py --- a/CodeAnalysis/GenerateOrthancSDK.py Tue Aug 12 13:50:34 2025 +0200 +++ b/CodeAnalysis/GenerateOrthancSDK.py Tue Aug 12 15:55:49 2025 +0200 @@ -189,9 +189,11 @@ return s -def GetShortName(name): +def GetShortName(name, parent_class = None): if not name.startswith('OrthancPlugin'): raise Exception() + elif parent_class != None and name.startswith(parent_class): + return name[len(parent_class):] else: return name[len('OrthancPlugin'):] @@ -208,6 +210,10 @@ 'type' : 'long int', 'format' : 'l', }, + 'int64_t' : { + 'type' : 'long long', + 'format' : 'L', + }, 'uint16_t' : { 'type' : 'unsigned short', 'format' : 'H', @@ -248,7 +254,7 @@ arg_type = GetShortName(a['sdk_enumeration']) elif a['sdk_type'] == 'const_object': arg_type = GetShortName(a['sdk_class']) - elif a['sdk_type'] in [ 'int32_t', 'uint32_t', 'uint8_t', 'uint16_t', 'uint64_t' ]: + elif a['sdk_type'] in [ 'int32_t', 'int64_t', 'uint32_t', 'uint8_t', 'uint16_t', 'uint64_t' ]: arg_type = 'int' elif a['sdk_type'] == 'Callable': # This is only used to generate the documentation file "orthanc.pyi" @@ -290,6 +296,9 @@ elif f['return_sdk_type'] == 'Tuple': # This is only used to generate the documentation file "orthanc.pyi" documentation['return_type'] = 'tuple' + elif f['return_sdk_type'] == 'bool': + # This is only used to generate the documentation file "orthanc.pyi" + documentation['return_type'] = 'bool' else: raise Exception('Return type not implemented: %s' % f['return_sdk_type']) @@ -299,10 +308,10 @@ return documentation -def FormatFunction(f): +def FormatFunction(f, parent_class = None): answer = { 'c_function' : f['c_function'], - 'short_name' : GetShortName(f['c_function']), + 'short_name' : GetShortName(f['c_function'], parent_class), 'has_args' : len(f['args']) > 0, 'count_args' : len(f['args']), } @@ -471,7 +480,7 @@ for m in c['methods']: if IsPrimitiveAvailable(m): - g = FormatFunction(m) + g = FormatFunction(m, parent_class = c['name']) if g != None: g['self'] = ', self->object_' methods.append(g) diff -r a65ba8bd5784 -r 919836e3fafd Resources/Orthanc/OrthancPluginCodeModel.json --- a/Resources/Orthanc/OrthancPluginCodeModel.json Tue Aug 12 13:50:34 2025 +0200 +++ b/Resources/Orthanc/OrthancPluginCodeModel.json Tue Aug 12 15:55:49 2025 +0200 @@ -5122,6 +5122,44 @@ "args": [ { "name": "arg0", + "sdk_name": "name", + "sdk_type": "const char *" + }, + { + "name": "arg1", + "sdk_name": "value", + "sdk_type": "int64_t" + }, + { + "name": "arg2", + "sdk_enumeration": "OrthancPluginMetricsType", + "sdk_name": "type", + "sdk_type": "enumeration" + } + ], + "c_function": "OrthancPluginSetMetricsIntegerValue", + "documentation": { + "args": { + "name": "The name of the metrics to be set.", + "type": "The type of the metrics. This parameter is only taken into consideration the first time this metrics is set.", + "value": "The value of the metrics." + }, + "description": [ + "This function sets the value of an integer metrics to monitor the behavior of the plugin through tools such as Prometheus. The values of all the metrics are stored within the Orthanc context." + ], + "summary": "Set the value of an integer metrics." + }, + "return_sdk_type": "void", + "since_sdk": [ + 1, + 12, + 1 + ] + }, + { + "args": [ + { + "name": "arg0", "sdk_name": "threadName", "sdk_type": "const char *" } diff -r a65ba8bd5784 -r 919836e3fafd Sources/Plugin.cpp --- a/Sources/Plugin.cpp Tue Aug 12 13:50:34 2025 +0200 +++ b/Sources/Plugin.cpp Tue Aug 12 15:55:49 2025 +0200 @@ -143,7 +143,7 @@ } else { - OrthancPluginDicomInstance* instance = reinterpret_cast(self)->object_; + OrthancPluginDicomInstance* instance = self->object_; const void* data; size_t size; @@ -185,7 +185,7 @@ } else { - OrthancPluginImage* image = reinterpret_cast(self)->object_; + OrthancPluginImage* image = self->object_; const void* buffer; size_t size; @@ -287,6 +287,75 @@ } +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 8) +PyObject* GetKeyValue(PyObject* module, PyObject* args) +{ + // The GIL is locked at this point (no need to create "PythonLock") + + const char* storeId = NULL; + const char* key = NULL; + + if (!PyArg_ParseTuple(args, "ss", &storeId, &key)) + { + PyErr_SetString(PyExc_TypeError, "Bad arguments"); + return NULL; + } + else + { + uint8_t found = 0; + OrthancPlugins::MemoryBuffer buffer; + OrthancPluginErrorCode code = OrthancPluginGetKeyValue(OrthancPlugins::GetGlobalContext(), &found, *buffer, storeId, key); + + if (code == OrthancPluginErrorCode_Success) + { + if (found) + { + return PyBytes_FromStringAndSize(reinterpret_cast(buffer.GetData()), buffer.GetSize()); + } + else + { + return Py_None; + } + } + else + { + PyErr_SetString(PyExc_TypeError, OrthancPluginGetErrorDescription(OrthancPlugins::GetGlobalContext(), code)); + return NULL; + } + } +} +#endif + + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 8) +PyObject* KeysValuesIteratorNext(sdk_OrthancPluginKeysValuesIterator_Object* self, PyObject *args) +{ + // The GIL is locked at this point (no need to create "PythonLock") + + if (self->object_ == NULL) + { + PyErr_SetString(PyExc_ValueError, "Invalid object"); + return NULL; + } + else + { + uint8_t done; + OrthancPluginErrorCode code = OrthancPluginKeysValuesIteratorNext(OrthancPlugins::GetGlobalContext(), &done, self->object_); + + if (code == OrthancPluginErrorCode_Success) + { + return PyBool_FromLong(done ? 1 : 0); + } + else + { + PyErr_SetString(PyExc_TypeError, OrthancPluginGetErrorDescription(OrthancPlugins::GetGlobalContext(), code)); + return NULL; + } + } +} +#endif + + #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 9) PyObject* SetStableStatus(PyObject* module, PyObject* args) {