来自其他线程的ctypes异步回调

ctypes asynchronous callback from other thread

我正在尝试从 C 线程接收异步回调,但是 Python 每次调用此类回调时都会崩溃。

这是 C 回调原型:

/*! Type declaration for the frame ready callback function.
@sa IC_SetFrameReadyCallback
@sa IC_SetCallbacks
@retval IC_SUCCESS Callback was set successfully
@retval IC_ERROR An error occurred, e.g. hGrabber is NULL.*/
typedef void (*FRAME_READY_CALLBACK)
    (HGRABBER hGrabber, unsigned char* pData, unsigned long frameNumber, void* );

这是注册回调的 C 函数:

/*! Enable frame ready callback.
@param hGrabber      Handle to a grabber object.
@param cb Callback function of type FRAME_READY_CALLBACK
@param x1_argument_in_void_userdata Pointer to some userdata.
@retval IC_SUCCESS Callback was set successfully
@retval IC_ERROR An error occurred, e.g. hGrabber is NULL.
@sa FRAME_READY_CALLBACK*/
int AC IC_SetFrameReadyCallback(
    HGRABBER                hGrabber,
    FRAME_READY_CALLBACK    cb,
    void*                   x1_argument_in_void_userdata);

最后,这是我的 Python 代码的一部分:

FRAME_READY_CALLBACK = CFUNCTYPE(c_int, ICGrabber, POINTER(c_ubyte), c_ulong, c_void_p)

...

library = windll.LoadLibrary('tisgrabber_x64')

...

IC_SetFrameReadyCallback = library.IC_SetFrameReadyCallback
IC_SetFrameReadyCallback.restype = c_int
IC_SetFrameReadyCallback.argtypes = [ICGrabber, FRAME_READY_CALLBACK, c_void_p]

...

def frame_ready(icGrabber, data, frameNumber, unused):
    print "oh"
    #print "Frame", frameNumber, "ready!!!"
    return 1


IC_InitLibrary(0) #library init function

...

IC_SetFrameReadyCallback(hGrabber, FRAME_READY_CALLBACK(frame_ready), None)

...

IC_SoftwareTrigger() #send signal
time.sleep(2) # while sleeping, the C thread calls the.. frame_ready callback

你猜怎么着?睡觉时,它崩溃了!

这是错误的代码:

IC_SetFrameReadyCallback(hGrabber, FRAME_READY_CALLBACK(frame_ready), None)

这是有效的:

cframe_ready = FRAME_READY_CALLBACK(frame_ready)
IC_SetFrameReadyCallback(grab, cframe_ready, None)

问题:

我没有保留对回调的引用,所以 Python 垃圾收集器清理了它。