DLL (PLC の製造元によって配布される C API インターフェイス) を介して PLC と通信しようとしています。他のソフトウェア (x64 - Windows 7) にスクリプト環境として組み込まれている Python 3.1.4 を使用しています。
以下のコールバック関数は、この組み込みスクリプト環境では機能しません (何も起こりません)。コールバック関数のトリガーが生成された後、スクリプトが開始および停止された後、Python が埋め込まれたソフトウェアが完全にクラッシュします。
コードは、スタンドアロンの python (3.1.4 MSC v1500 64 ビット AMD も同様) で正常に動作します。
組み込み Python でコールバックを使用しない DLL の他の関数を正常に実装しました。
それが何であるかを知っている人はいますか?
def callback_func(amsaddr,notifHeader,huser):
print('do something')
pass
CMPFUNC = WINFUNCTYPE(None,POINTER(AmsAddr),POINTER(AdsNotificationHeader),c_ulong)
cmp_func = CMPFUNC(callback_func)
netId = AmsNetId((c_ubyte*6)(5,18,18,27,1,1))
plcAddress = AmsAddr(netId,801)
nIndexGroup = c_ulong(0xF021)
nIndexOffset = c_ulong(0x0)
adsNotif = AdsNotificationAttrib(1,4,1000000,1000000)
handle = c_ulong()
huser = c_ulong(10)
ADS_DLL = WinDLL("C:/Program Files/TwinCAT/Ads Api/TcAdsDll/x64/TcAdsDll.dll")
ADS_DLL.AdsSyncAddDeviceNotificationReq.argtypes=[POINTER(AmsAddr),c_ulong,c_ulong,POINTER(AdsNotificationAttrib),CMPFUNC,c_ulong,POINTER(c_ulong)]
ADS_DLL.AdsSyncAddDeviceNotificationReq.restype=c_long
#Function in the DLL with the callback
errCode = ADS_DLL.AdsSyncAddDeviceNotificationReq(pointer(plcAddress),nIndexGroup,nIndexOffset,pointer(adsNotif),cmp_func,huser,pointer(handle))
print('Device Notification error Code : %s' %errCode)
編集 ^2
単純な ctypes コールバックを試してみましたが、組み込みの python バージョンでは惨めに失敗しました...ソフトウェアがハングするだけで、タスクマネージャーでそれを強制終了する必要があります。次のコードを試しました(ドキュメントから):
from ctypes import *
IntArray5 = c_int * 5
ia = IntArray5(5, 1, 7, 33, 99)
libc = cdll.msvcrt #or libc = cdll.msvcr90 --> same problem
qsort = libc.qsort
qsort.restype = None
CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
def py_cmp_func(a, b):
print("py_cmp_func", a[0], b[0])
return 0
cmp_func = CMPFUNC(py_cmp_func)
qsort(ia, len(ia), sizeof(c_int), cmp_func)
編集 ^3
スレッドを使用していくつかの改善を得ることができました。print() 関数だけがコールバックで何も出力しません...たとえば、 os.system('c:/windows/notepad.exe') などの他の関数も機能しません。
from ctypes import *
import threading, queue
import os
IntArray5 = c_int * 5
ia = IntArray5(5, 1, 7, 33, 99)
libc = cdll.msvcrt
qsort = libc.qsort
qsort.restype = None
q = queue.Queue()
CMPFUNC = CFUNCTYPE(None,POINTER(c_int), POINTER(c_int))
def py_cmp_func(a, b):
print("py_cmp_func", a[0], b[0]) #--> doesn't print anything
print('Callback, in thread %s' % threading.current_thread().name) #--> doesn't print anything
q.put('something')
cmp_func = CMPFUNC(py_cmp_func)
t = threading.Thread(target=qsort, args=(ia, len(ia), sizeof(c_int), cmp_func))
t.start()
print(threading.enumerate()) #--> prints [<Thread(Thread-1, started 2068)>, <_MainThread(MainThread, started 2956)>]
t.join()
print(threading.enumerate()) # --> prints [<_MainThread(MainThread, started 2956)>]
print(q.get()) #--> prints 'something'