![](/img/trans.png)
[英]How to allocate memory to a C callback function with ctypes and threading
[英]Using threading lock in ctypes callback function
我想從扭曲的應用程序中使用ctypes dll。 最小的例子在這里炮制:
from ctypes import *
from threading import Lock
lock = Lock()
dll = windll.LoadLibrary('mydll.dll')
l = [1,2,3]
def callback():
lock.acquire()
l.pop()
lock.release()
return 0
C_CALLBACK = CFUNCTYPE(c_int)
c_callback = C_CALLBACK(callback)
# this is a non blocking function call starts a hardware task that fires a callback upon completion
dll.registerCallback(c_callback)
while(True):
# in reality this block gets called from a twisted server application
lock.acquire()
l.append(l.pop() + 1)
lock.release()
dll有一個函數( dll.registerCallback
),它接受ctypes回調函數,啟動硬件事件,並在硬件指示硬件任務完成時觸發回調。
從API文檔:
回調函數在DAQmx線程中調用。
在網絡上的某個地方,他們試圖解釋“DAQmx線程”是什么:
...您的回調將在DAQmx驅動程序線程中調用並運行,並且將與您的程序異步運行(不在同一個線程中)。
完整的文檔可以在這里找到。 為簡單起見,我在我的示例中更改了函數簽名。
所以我想我們可以安全地假設dll正在產生一個線程。
我現有的鎖是否確保回調函數在主循環中pop
操作的中間時不會嘗試訪問列表l
,反之亦然? 或者,此方案僅在使用使用threading
庫創建的threading
時才有效? 這里的推薦做法是什么?
ctypes _CallPythonObject
做的第一件事是調用PyGILState_Ensure()
,如果需要,它將調用PyThreadState_New
來創建一個新的線程狀態。 除此之外,它是vanilla Python線程代碼,所以你的鎖應該可以正常工作。 它在下面的示例中適用於我(Linux,Python 2.7.3):
from ctypes import *
import threading
lock = threading.Lock()
lib = CDLL('./tmp.so')
callback_t = CFUNCTYPE(c_int)
def f():
with lock:
print threading.current_thread()
return 21
callback = callback_t(f)
lib.registerCallback(callback)
>>> lock.acquire()
True
>>> t = threading.Thread(target=lib.event)
>>> t.start()
>>> lock.locked()
True
>>> lock.release()
>>> <_DummyThread(Dummy-2, started daemon -1230402704)>
res: 21
DummyThread
輸出來自打印回調中的當前線程。 在Python之外創建的線程獲得一個“虛擬”名稱。
tmp.c:
#include <stdio.h>
#include <pthread.h>
typedef int (*callback_t)(void);
callback_t callback = NULL;
void *doCallback(void *arg)
{
int res = callback();
printf("res: %d\n", res);
pthread_exit(0);
}
int event(void)
{
pthread_t callback_thread;
pthread_create(&callback_thread, NULL, doCallback, NULL);
pthread_join(callback_thread, NULL);
return 0;
}
int registerCallback(callback_t foo)
{
callback = foo;
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.