--- a/py_ext/PythonFileCTNMixin.py Mon Dec 07 09:49:34 2020 +0100
+++ b/py_ext/PythonFileCTNMixin.py Thu Dec 10 11:37:27 2020 +0100
@@ -169,10 +169,14 @@
-""" % varinfo for varinfo in varinfos])
+_PyOnChangeCount_%(name)s = ctypes.c_uint.in_dll(PLCBinary,"__%(name)s_onchange_count") +_PyOnChangeFirst_%(name)s = _%(name)s_ctype.in_dll(PLCBinary,"__%(name)s_onchange_firstval") +_PyOnChangeLast_%(name)s = _%(name)s_ctype.in_dll(PLCBinary,"__%(name)s_onchange_lastval") +""" % varinfo if varinfo["onchange"] else "") for varinfo in varinfos]) on_change_func_body = "\n".join(["""
+ if _PyOnChangeCount_%(name)s.value > 0: @@ -215,7 +219,7 @@
_PySafeGetChanges_%(pyextname)s = PLCBinary.PySafeGetChanges_%(location_str)s
-_PySafeGetChanges_%(pyextname)s.restype = ctypes.POINTER(ctypes.c_int * %(onchange_var_count)d)
+_PySafeGetChanges_%(pyextname)s.restype = None _PySafeGetChanges_%(pyextname)s.argtypes = None
_%(pyextname)sGlobalsDesc = []
@@ -230,10 +234,7 @@
def On_%(pyextname)s_Change():
- changesP = _PySafeGetChanges_%(pyextname)s()
- raise Exception("PySafeGetChanges returned NULL!")
- changes = iter(changesP.contents)
+ _PySafeGetChanges_%(pyextname)s() @@ -274,7 +275,12 @@
-int __%(name)s_rbuffer_written = 0;
+unsigned int __%(name)s_rbuffer_written = 0; +IEC_%(IECtype)s __%(name)s_rbuffer_firstval; +IEC_%(IECtype)s __%(name)s_rbuffer_lastval; +unsigned int __%(name)s_onchange_count = 0; +IEC_%(IECtype)s __%(name)s_onchange_firstval; +IEC_%(IECtype)s __%(name)s_onchange_lastval; @@ -297,21 +303,26 @@
if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){
IEC_%(IECtype)s tmp = __GET_VAR(%(configname)s__%(uppername)s);
if(NE_%(IECtype)s(1, NULL, __%(name)s_rbuffer, tmp)){
+ if(__%(name)s_rbuffer_written == 0); + __%(name)s_rbuffer_firstval = __%(name)s_rbuffer; + __%(name)s_rbuffer_lastval = tmp; __%(name)s_rbuffer = tmp;
- /* mark variable as changed */
- __%(name)s_rbuffer_written = 1;
+ /* count one more change */ + __%(name)s_rbuffer_written += 1; AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
varcollectchangefmt = """\
- while(AtomicCompareExchange(&__%(name)s_wlock, 0, 1));
- pysafe_changes[change_index++] = __%(name)s_rbuffer_written;
+ while(AtomicCompareExchange(&__%(name)s_rlock, 0, 1)); + __%(name)s_onchange_count = __%(name)s_rbuffer_written; + __%(name)s_onchange_firstval = __%(name)s_rbuffer_firstval; + __%(name)s_onchange_lastval = __%(name)s_rbuffer_lastval; /* mark variable as unchanged */
__%(name)s_rbuffer_written = 0;
- AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0);
+ AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0); vardec = "\n".join([(vardecfmt + vardeconchangefmt
@@ -371,20 +382,20 @@
+static int passing_changes_to_python = 0; void __publish_%(location_str)s(void){
+ int some_change_found = 0; + passing_changes_to_python |= some_change_found; // call python part if there was at least a change
+ if(passing_changes_to_python){ PYTHON_POLL_body__(__%(location_str)s_notifier);
+ passing_changes_to_python &= !(__GET_VAR(__%(location_str)s_notifier->ACK,)); -static int pysafe_changes[%(onchange_var_count)d];
void* PySafeGetChanges_%(location_str)s(void){
- return (void*)&pysafe_changes[0];
--- a/runtime/PLCObject.py Mon Dec 07 09:49:34 2020 +0100
+++ b/runtime/PLCObject.py Thu Dec 10 11:37:27 2020 +0100
@@ -360,8 +360,19 @@
v = parent.python_runtime_vars["_"+name+"_pack"](t, value)
parent.python_runtime_vars["_PySafeSetPLCGlob_"+name](ctypes.byref(v))
+ class OnChangeStateClass(object): + def __getattr__(self, name): + u = parent.python_runtime_vars["_"+name+"_unpack"] + res.count = parent.python_runtime_vars["_PyOnChangeCount_"+name].value + res.first = u(parent.python_runtime_vars["_PyOnChangeFirst_"+name]) + res.last = u(parent.python_runtime_vars["_PyOnChangeLast_"+name]) self.python_runtime_vars.update({
"PLCGlobals": PLCSafeGlobals(),
+ "OnChange": OnChangeStateClass(), "WorkingDir": self.workingdir,
"PLCBinary": self.PLClibraryHandle,