如何使用ctypes和线程

时间:2016-08-02 20:41:18

标签: python c multithreading ctypes

我目前正在为相机软件编写python绑定。商业SDK仅包含文档和DLL。我没有C代码,但我会尽量清楚,所以请耐心等待。

我让所有的库函数都工作但只有一个:一个获取图片的回调函数。该文档仅提供函数原型:

  

foo:在指定端口上启动图像采集。返回错误代码。

int foo(HANDLE dev, char port, int queueMode, callback_type fnCallback, void * userInfo );
  

callback_type:接收的应用程序定义的回调函数   有关获得的框架的信息。

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:没有足够的内存来执行操作(根据文档)。 当我再次(再次)调用它时,它总是返回0,这是成功的,但是队列保持为空并且它从不打印"我在这里"。

然后我尝试添加一个帖子:

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

我也尝试过不使用run()并在启动线程后直接调用该函数。它还没有工作。 我真的不知道这里发生了什么。我对线程和ctypes很新,但我的猜测是库使用自己的线程来返回照片,我不知何故应该为这个回调函数分配内存。但是怎么样? 任何解决方案/评论将不胜感激。谢谢!

_编辑:文档中的示例代码_

* \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)

它停止了该计划。

1 个答案:

答案 0 :(得分:1)

如果没有完整的例子,我不确定你哪里出错了。你宣布foo.argtypes了吗?您确定这些函数__stdcall适用于WinDLLWINFUNCTYPE,还是__cdecl且需要CDLLCFUNCTYPE

这是一个使用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)