我是否正确使用ctypes来pythonify这个结构?

时间:2014-09-13 00:32:32

标签: python c++ c dll ctypes

我正在尝试使用python的ctypes与this DLL交谈。许多函数采用或返回HGRABBER类型:

typedef struct HGRABBER_t__ { int unused; } HGRABBER_t;
#define HGRABBER HGRABBER_t* 

(可以查看完整的头文件here)。这是一个返回HGRABBER类型的函数原型的示例:

HGRABBER __stdcall IC_CreateGrabber();

这是我尝试在python中实现这个结构,并使用它从DLL调用该函数:

import ctypes as C
class GrabberHandle(C.Structure):
    _fields_ = [('unused', C.c_int)]

dll = C.windll.LoadLibrary('tisgrabber_x64.dll')
dll.create_grabber = dll.IC_CreateGrabber
dll.create_grabber.argtypes = []
dll.create_grabber.restype = GrabberHandle
my_handle = dll.create_grabber()

这似乎有效,但我担心我做错了。我对C没有经验,我认为我不理解定义typedef类型的#defineHGRABBER语句。 我是否正确调用IC_CreateGrabber我是否应该将GrabberHandle定义为指向结构的指针而不是结构?

感谢您阅读,如果我能以某种方式澄清我的问题,请告诉我。

2 个答案:

答案 0 :(得分:2)

你确实想要POINTERStructure,而不是Structure本身。你是对的。

将C翻译成英文,非常宽松(如果你试图学习C但在使用ctypes时已经足够好了):

  • struct定义了一个名为struct HGRABBER_t__的类型,作为其中包含一个int的结构。
  • typedef定义了一个名为HGRABBER_t的类型,作为struct HGRABBER_t__的同义词。
  • #define将名为HGRABBER的类型定义为指向HGRABBER_t的指针。

因此,您的GrabberHandle相当于HGRABBER_t;相当于HGRABBER的是:

GrabberHandlePtr = C.POINTER(GrabberHandle)

所以你想要这个:

dll.create_grabber.restype = GrabberHandlePtr

调整差异可能很难。只有int的C结构看起来与内存中的int相同。在Win32上,int和指针都是32位值。而一个名为unused的int可能会被无意义的垃圾填满,这使得很难将它与你不小心被视为int的指针区分开来。所以一切都会好起来,直到你的代码后面有30行,并且不知道出了什么问题。 :)

答案 1 :(得分:1)

这个库完成了你要做的事情:https://github.com/morefigs/py-ic-imaging-control:)

但是为了回答你的问题,图书馆使用代码:

from ctypes import *
import os

class GrabberHandle(Structure):
    pass
GrabberHandle._fields_ = [('unused', c_int)]

# set and check path
dll_path = os.path.join(os.path.expanduser('~'),
                        'Documents\\The Imaging Source Europe GmbH\\TIS Grabber DLL\\bin\\win32\\tisgrabber.dll')
with open(dll_path) as thefile:
    pass

# open DLL
_ic_grabber_dll = windll.LoadLibrary(dll_path)

# create grabber
create_grabber = _ic_grabber_dll.IC_CreateGrabber
create_grabber.restype = POINTER(GrabberHandle)
create_grabber.argtypes = None

# get handle
handle = create_grabber()

编辑:根据abarnert的回答更改代码以使用指向GrabberHandle的指针,因为这是正确的。但是,在这种特殊情况下,我发现没有实际的区别(使用32位DLL),可能是因为GrabberHandle结构非常简单。