如何使用 ctypes 和线程将内存分配给 C 回调函数
How to allocate memory to a C callback function with ctypes and threading
我目前正在为相机软件编写 python 绑定。商业 SDK 仅包含文档和 DLL。我没有 C 代码,但我会尽可能清楚,所以请多多包涵。
我可以使用所有库函数,但只有一个:获取图片的回调函数。文档仅提供函数原型:
foo: Starts image acquisition on specified port. Return error code.
int foo(HANDLE dev, char port, int queueMode, callback_type fnCallback, void * userInfo );
callback_type: Application-defined callback function that recieves
information about acquired frame.
void callback_type(void * userInfo, photoStruct* photo);
这是我在加载库并包装函数和结构后的 python 代码。
callback_type = WINFUNCTYPE(None,c_void_p,POINTER(photoStruct))
def my_callback(userInfo, photoInfo):
if(photoInfo.status == 0):
#Process incoming photo
print "I'm here" #for debugging purposes
q.put(photoInfo.rawBuffer[:photoInfo.bufferSize])
q.task_done()
_my_callback = callback_type(my_callback)
每当我第一次尝试调用 foo 时:
>>>lib.foo(dev, port, c_int(0), _my_callback, None)
我收到错误代码 4:内存不足,无法执行操作(根据文档)。
当我再次(又一次)调用它时,它 returns 始终为 0,这是成功的,但队列保持为空并且它从不打印 "I'm here".
然后我尝试添加一个线程:
ty = threading.Thread(target=lib.foo, args=(dev,port, c_int(0), _my_callback, None))
>>> ty.start()
>>> ty.run()
line 758, in run
del self.__target, self.__args, self.__kwargs
AttributeError: _Thread__target
我也试过不使用 运行() 并在启动线程后直接调用该函数。它仍然不起作用。
我真的不知道这里发生了什么。我对线程和 ctypes 很陌生,但我的猜测是该库使用自己的线程来 return 照片,我应该以某种方式为此回调函数分配内存。但是怎么办?
任何 solutions/comments 将不胜感激。谢谢!
_ 编辑:文档中的示例代码 _
* \sample
* \code
* void __stdcall callback_type(void* userInfo, photoStruct* photo)
* {
* // Process incoming photo
* }
* ...
* foo(dev, port, 0, &callback_type, NULL);
* ...
* \endcode
*/
我试图在 Python 中用
调用 foo
>>>lib.foo(dev, port, c_int(0), byref(_my_callback), None)
它停止了程序。
如果没有完整的示例,我不确定您哪里出错了。你声明了foo.argtypes
吗?您确定函数 __stdcall
用于 WinDLL
和 WINFUNCTYPE
,还是 __cdecl
需要 CDLL
和 CFUNCTYPE
?
这是一个使用以下 DLL 测试代码的工作示例:
typedef void* HANDLE;
typedef struct {
int value;
} photoStruct;
typedef void (__stdcall * callback_type)(void * userInfo, photoStruct* photo);
__declspec(dllexport) int __stdcall foo(HANDLE dev, char port, int queueMode, callback_type fnCallback, void * userInfo)
{
photoStruct p;
p.value = 123;
fnCallback(userInfo, &p);
return 0;
}
Python代码:
#!python2
from ctypes import *
HANDLE = c_void_p
class photoStruct(Structure):
_fields_ = [('value',c_int)]
def __repr__(self):
return 'photoStruct(value={})'.format(self.value)
callback_type = WINFUNCTYPE(None,c_void_p,POINTER(photoStruct))
@callback_type
def my_callback(userInfo, photo):
print userInfo,photo.contents
foo = WinDLL('test').foo
foo.argtypes = (HANDLE,c_char,c_int,callback_type,c_void_p)
foo.restype = c_int
foo(1,'2',3,my_callback,None)
输出:
None photoStruct(value=123)
我目前正在为相机软件编写 python 绑定。商业 SDK 仅包含文档和 DLL。我没有 C 代码,但我会尽可能清楚,所以请多多包涵。
我可以使用所有库函数,但只有一个:获取图片的回调函数。文档仅提供函数原型:
foo: Starts image acquisition on specified port. Return error code.
int foo(HANDLE dev, char port, int queueMode, callback_type fnCallback, void * userInfo );
callback_type: Application-defined callback function that recieves information about acquired frame.
void callback_type(void * userInfo, photoStruct* photo);
这是我在加载库并包装函数和结构后的 python 代码。
callback_type = WINFUNCTYPE(None,c_void_p,POINTER(photoStruct))
def my_callback(userInfo, photoInfo):
if(photoInfo.status == 0):
#Process incoming photo
print "I'm here" #for debugging purposes
q.put(photoInfo.rawBuffer[:photoInfo.bufferSize])
q.task_done()
_my_callback = callback_type(my_callback)
每当我第一次尝试调用 foo 时:
>>>lib.foo(dev, port, c_int(0), _my_callback, None)
我收到错误代码 4:内存不足,无法执行操作(根据文档)。 当我再次(又一次)调用它时,它 returns 始终为 0,这是成功的,但队列保持为空并且它从不打印 "I'm here".
然后我尝试添加一个线程:
ty = threading.Thread(target=lib.foo, args=(dev,port, c_int(0), _my_callback, None))
>>> ty.start()
>>> ty.run()
line 758, in run
del self.__target, self.__args, self.__kwargs
AttributeError: _Thread__target
我也试过不使用 运行() 并在启动线程后直接调用该函数。它仍然不起作用。 我真的不知道这里发生了什么。我对线程和 ctypes 很陌生,但我的猜测是该库使用自己的线程来 return 照片,我应该以某种方式为此回调函数分配内存。但是怎么办? 任何 solutions/comments 将不胜感激。谢谢!
_ 编辑:文档中的示例代码 _
* \sample
* \code
* void __stdcall callback_type(void* userInfo, photoStruct* photo)
* {
* // Process incoming photo
* }
* ...
* foo(dev, port, 0, &callback_type, NULL);
* ...
* \endcode
*/
我试图在 Python 中用
调用 foo>>>lib.foo(dev, port, c_int(0), byref(_my_callback), None)
它停止了程序。
如果没有完整的示例,我不确定您哪里出错了。你声明了foo.argtypes
吗?您确定函数 __stdcall
用于 WinDLL
和 WINFUNCTYPE
,还是 __cdecl
需要 CDLL
和 CFUNCTYPE
?
这是一个使用以下 DLL 测试代码的工作示例:
typedef void* HANDLE;
typedef struct {
int value;
} photoStruct;
typedef void (__stdcall * callback_type)(void * userInfo, photoStruct* photo);
__declspec(dllexport) int __stdcall foo(HANDLE dev, char port, int queueMode, callback_type fnCallback, void * userInfo)
{
photoStruct p;
p.value = 123;
fnCallback(userInfo, &p);
return 0;
}
Python代码:
#!python2
from ctypes import *
HANDLE = c_void_p
class photoStruct(Structure):
_fields_ = [('value',c_int)]
def __repr__(self):
return 'photoStruct(value={})'.format(self.value)
callback_type = WINFUNCTYPE(None,c_void_p,POINTER(photoStruct))
@callback_type
def my_callback(userInfo, photo):
print userInfo,photo.contents
foo = WinDLL('test').foo
foo.argtypes = (HANDLE,c_char,c_int,callback_type,c_void_p)
foo.restype = c_int
foo(1,'2',3,my_callback,None)
输出:
None photoStruct(value=123)