From 8b43a644b13fdcc18463cee150eeb6613fc29ae7 Mon Sep 17 00:00:00 2001 From: Thibaut Vermeulen Date: Wed, 4 May 2022 18:23:39 +0200 Subject: [PATCH] python service wrapper: add state management for blocking IO in python --- pyiec61850/iec61850.i | 6 +++ pyiec61850/servicePythonWrapper.hpp | 63 +++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 pyiec61850/servicePythonWrapper.hpp diff --git a/pyiec61850/iec61850.i b/pyiec61850/iec61850.i index e4542544..254fec64 100644 --- a/pyiec61850/iec61850.i +++ b/pyiec61850/iec61850.i @@ -154,3 +154,9 @@ void CommParameters_setDstAddress(CommParameters *gooseCommParameters, uint8_t dst_mac_4, uint8_t dst_mac_5); + +/* Wrapper for synchronous functions */ +%{ +#include "servicePythonWrapper.hpp" +%} +%include "servicePythonWrapper.hpp" diff --git a/pyiec61850/servicePythonWrapper.hpp b/pyiec61850/servicePythonWrapper.hpp new file mode 100644 index 00000000..369e86c3 --- /dev/null +++ b/pyiec61850/servicePythonWrapper.hpp @@ -0,0 +1,63 @@ +#ifndef PYIEC61850_SERVICEPYTHONWRAPPER_HPP +#define PYIEC61850_SERVICEPYTHONWRAPPER_HPP + +#include "iec61850_client.h" +#include + + +class PyThreadStateSave +{ +public: + PyThreadStateSave(void) + { + if (PyGILState_Check()) + state = PyEval_SaveThread(); + else + state = nullptr; + } + + ~PyThreadStateSave(void) + { + if (state) + PyEval_RestoreThread(state); + } + +private: + PyThreadState* state; +}; + +/* +Wrapping of synchronous functions to prevent deadlocks +*/ +static MmsValue* +pyWrap_IedConnection_readObject(IedConnection con, IedClientError* error, const char* objRef, FunctionalConstraint fc) +{ + PyThreadStateSave gilStateSave; + return IedConnection_readObject(con, error, objRef, fc); +} + +static void +pyWrap_IedConnection_writeObject(IedConnection con, IedClientError* error, const char* objectReference, + FunctionalConstraint fc, MmsValue* value) +{ + PyThreadStateSave gilStateSave; + IedConnection_writeObject(con, error, objectReference, fc, value); +} + +static void +pyWrap_IedConnection_setRCBValues(IedConnection con, IedClientError* error, ClientReportControlBlock rcb, uint32_t parametersMask, + bool singleRequest) +{ + PyThreadStateSave gilStateSave; + IedConnection_setRCBValues(con, error, rcb, parametersMask, singleRequest); +} + +static ClientReportControlBlock +pyWrap_IedConnection_getRCBValues(IedConnection con, IedClientError* error, const char* rcbReference, + ClientReportControlBlock updateRcb) +{ + PyThreadStateSave gilStateSave; + return IedConnection_getRCBValues(con, error, rcbReference, updateRcb); +} + +#endif