我正在尝试与 this DLL 通话使用 python 的 ctypes。许多函数采用或返回 HGRABBER
类型:
typedef struct HGRABBER_t__ { int unused; } HGRABBER_t;
#define HGRABBER HGRABBER_t*
(完整的头文件可以查看here)。下面是一个返回 HGRABBER
类型的函数原型(prototype)示例:
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 语言的经验,而且我不认为我理解定义 HGRABBER
类型的 typedef
和 #define
语句。 我是否正确调用了 IC_CreateGrabber
?我是否应该将 GrabberHandle 定义为指向结构的指针,而不是结构?
感谢阅读,如果我能以某种方式澄清我的问题,请告诉我。
最佳答案
你是对的,你实际上想要一个指向 Structure
的 POINTER
,而不是 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 行并且不知道出了什么问题。 :)
关于python - 我是否正确使用 ctypes 来 pythonify 这个结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25818697/