我正在尝试使用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
类型的#define
和HGRABBER
语句。 我是否正确调用IC_CreateGrabber
?我是否应该将GrabberHandle定义为指向结构的指针而不是结构?
感谢您阅读,如果我能以某种方式澄清我的问题,请告诉我。
答案 0 :(得分:2)
你确实想要POINTER
到Structure
,而不是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
结构非常简单。