84 def _LoadNewPLC(self): |
84 def _LoadNewPLC(self): |
85 """ |
85 """ |
86 Load PLC library |
86 Load PLC library |
87 Declare all functions, arguments and return values |
87 Declare all functions, arguments and return values |
88 """ |
88 """ |
89 PLCprint("Load PLC") |
|
90 try: |
89 try: |
91 self._PLClibraryHandle = dlopen(self._GetLibFileName()) |
90 self._PLClibraryHandle = dlopen(self._GetLibFileName()) |
92 self.PLClibraryHandle = ctypes.CDLL(self.CurrentPLCFilename, handle=self._PLClibraryHandle) |
91 self.PLClibraryHandle = ctypes.CDLL(self.CurrentPLCFilename, handle=self._PLClibraryHandle) |
93 |
92 |
94 self._startPLC = self.PLClibraryHandle.startPLC |
93 self._startPLC = self.PLClibraryHandle.startPLC |
101 self._PythonIterator = getattr(self.PLClibraryHandle, "PythonIterator", None) |
100 self._PythonIterator = getattr(self.PLClibraryHandle, "PythonIterator", None) |
102 if self._PythonIterator is not None: |
101 if self._PythonIterator is not None: |
103 self._PythonIterator.restype = ctypes.c_char_p |
102 self._PythonIterator.restype = ctypes.c_char_p |
104 self._PythonIterator.argtypes = [ctypes.c_char_p] |
103 self._PythonIterator.argtypes = [ctypes.c_char_p] |
105 |
104 |
106 def StopPLCLock(): |
105 self._stopPLC = self._stopPLC_real |
107 self.PLClibraryLock.acquire() |
|
108 self._stopPLC_real() |
|
109 self.PLClibraryLock.release() |
|
110 |
|
111 else: |
106 else: |
112 # If python plugin is not enabled, we reuse _PythonIterator |
107 # If python plugin is not enabled, we reuse _PythonIterator |
113 # as a call that block pythonthread until StopPLC |
108 # as a call that block pythonthread until StopPLC |
114 self.PythonIteratorLock = Lock() |
109 self.PythonIteratorLock = Lock() |
115 self.PythonIteratorLock.acquire() |
110 self.PythonIteratorLock.acquire() |
117 self.PythonIteratorLock.acquire() |
112 self.PythonIteratorLock.acquire() |
118 self.PythonIteratorLock.release() |
113 self.PythonIteratorLock.release() |
119 return None |
114 return None |
120 self._PythonIterator = PythonIterator |
115 self._PythonIterator = PythonIterator |
121 |
116 |
122 def StopPLCLock(): |
117 def __StopPLC(): |
123 self.PLClibraryLock.acquire() |
|
124 self._stopPLC_real() |
118 self._stopPLC_real() |
125 self.PythonIteratorLock.release() |
119 self.PythonIteratorLock.release() |
126 self.PLClibraryLock.release() |
120 self._stopPLC = __StopPLC |
127 |
121 |
128 self._stopPLC = StopPLCLock |
|
129 |
122 |
130 self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables |
123 self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables |
131 self._ResetDebugVariables.restype = None |
124 self._ResetDebugVariables.restype = None |
132 |
125 |
133 self._RegisterDebugVariable = self.PLClibraryHandle.RegisterDebugVariable |
126 self._RegisterDebugVariable = self.PLClibraryHandle.RegisterDebugVariable |
161 self.PLClibraryLock.acquire() |
154 self.PLClibraryLock.acquire() |
162 # Forget all refs to library |
155 # Forget all refs to library |
163 self._startPLC = lambda:None |
156 self._startPLC = lambda:None |
164 self._stopPLC = lambda:None |
157 self._stopPLC = lambda:None |
165 self._ResetDebugVariables = lambda:None |
158 self._ResetDebugVariables = lambda:None |
166 self._RegisterDebugVariable = lambda x:None |
159 self._RegisterDebugVariable = lambda x, y:None |
167 self._IterDebugData = lambda x,y:None |
160 self._IterDebugData = lambda x,y:None |
168 self._FreeDebugData = lambda:None |
161 self._FreeDebugData = lambda:None |
169 self._GetDebugData = lambda:-1 |
162 self._GetDebugData = lambda:-1 |
170 self._suspendDebug = lambda x:None |
163 self._suspendDebug = lambda x:None |
171 self._resumeDebug = lambda:None |
164 self._resumeDebug = lambda:None |
215 if self.website is not None: |
208 if self.website is not None: |
216 self.website.PLCStopped() |
209 self.website.PLCStopped() |
217 self.python_threads_vars = None |
210 self.python_threads_vars = None |
218 |
211 |
219 def PythonThreadProc(self): |
212 def PythonThreadProc(self): |
220 PLCprint("PythonThreadProc started") |
|
221 c_argv = ctypes.c_char_p * len(self.argv) |
213 c_argv = ctypes.c_char_p * len(self.argv) |
222 error = None |
214 error = None |
223 if self._LoadNewPLC(): |
215 if self._LoadNewPLC(): |
224 if self._startPLC(len(self.argv),c_argv(*self.argv)) == 0: |
216 if self._startPLC(len(self.argv),c_argv(*self.argv)) == 0: |
225 self.PLCStatus = "Started" |
217 self.PLCStatus = "Started" |
382 """ |
374 """ |
383 Return a list of variables, corresponding to the list of required idx |
375 Return a list of variables, corresponding to the list of required idx |
384 """ |
376 """ |
385 if self.PLCStatus == "Started": |
377 if self.PLCStatus == "Started": |
386 res=[] |
378 res=[] |
387 self.PLClibraryLock.acquire() |
|
388 tick = ctypes.c_uint32() |
379 tick = ctypes.c_uint32() |
389 size = ctypes.c_uint32() |
380 size = ctypes.c_uint32() |
390 buffer = ctypes.c_void_p() |
381 buffer = ctypes.c_void_p() |
391 offset = 0 |
382 offset = 0 |
392 if self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 : |
383 if self.PLClibraryLock.acquire(False) and \ |
393 for idx, iectype, forced in self._Idxs: |
384 self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 : |
394 cursor = ctypes.c_void_p(buffer.value + offset) |
385 if size.value: |
395 c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None)) |
386 for idx, iectype, forced in self._Idxs: |
396 if c_type is not None and offset < size: |
387 cursor = ctypes.c_void_p(buffer.value + offset) |
397 res.append(unpack_func(ctypes.cast(cursor, |
388 c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None)) |
398 ctypes.POINTER(c_type)).contents)) |
389 if c_type is not None and offset < size: |
399 offset += ctypes.sizeof(c_type) |
390 res.append(unpack_func(ctypes.cast(cursor, |
400 else: |
391 ctypes.POINTER(c_type)).contents)) |
401 if c_type is None: |
392 offset += ctypes.sizeof(c_type) |
402 PLCprint("Debug error - " + iectype + " not supported !") |
393 else: |
403 if offset >= size: |
394 if c_type is None: |
404 PLCprint("Debug error - buffer too small !") |
395 PLCprint("Debug error - " + iectype + " not supported !") |
405 break |
396 if offset >= size: |
406 self._FreeDebugData() |
397 PLCprint("Debug error - buffer too small !") |
407 self.PLClibraryLock.release() |
398 break |
|
399 self._FreeDebugData() |
|
400 self.PLClibraryLock.release() |
408 if offset and offset == size.value: |
401 if offset and offset == size.value: |
409 return self.PLCStatus, tick.value, res |
402 return self.PLCStatus, tick.value, res |
410 else: |
403 elif size.value: |
411 PLCprint("Debug error - bad buffer unpack !") |
404 PLCprint("Debug error - wrong buffer unpack !") |
412 return self.PLCStatus, None, None |
405 return self.PLCStatus, None, None |
413 |
406 |