如何使用 ctypes 读取具有自定义结构的 dll 的输出?
How to read output of a dll with custom structure using ctypes?
我正在使用一个名为 CL3_IF.dll 的 DLL,其文档中将其描述为:
格式:CL3IF_VERSION_INFO CL3IF_GetVersion(void)
参数:—
Return 值:
Return此 DLL 的版本。
typedef struct {
INT majorNumber;
INT minorNumber;
INT revisionNumber;
INT buildNumber;
} CL3IF_VERSION_INFO;
说明:该函数获取DLL版本。
我使用了以下 python 代码:
import ctypes
CLP=ctypes.WinDLL('CL3_IF.dll')
class CLIF_VERSION_INFO(ctypes.Structure):
_fields_ = [("majorNumber", ctypes.c_int),
("minorNumber", ctypes.c_int),
("revisionNumber", ctypes.c_int),
("buildNumber", ctypes.c_int)]
CLP.CL3IF_GetVersion(ctypes.c_void_p, CLIF_VERSION_INFO)
当我运行上面的代码时,我得到以下错误:
ArgumentError: argument 1: <class 'TypeError'>: Don't know how to convert parameter 1
我希望能够以可用的形式获取版本信息,并且 dll 的许多其他函数以复杂的结构提供它们的输出。
我将使用的最复杂的函数是 this
如果有人知道我将如何阅读此输出,我将不胜感激。
returned结构是一个return值,不是参数,void
表示没有参数,而c_void_p
表示有void*
参数.确保正确设置 .argtypes
和 .restype
。
另请注意,WinDLL
适用于 32 位 __stdcall
API。将 CDLL
用于 __cdecl
(C 调用约定)API。在 64 位 Python 上两者都可以工作,因为只有一种调用约定,但对于可移植代码,请使用正确的约定。
完整示例如下:
test.cpp
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef int INT;
typedef struct {
INT majorNumber;
INT minorNumber;
INT revisionNumber;
INT buildNumber;
} CL3IF_VERSION_INFO;
extern "C"
{
API CL3IF_VERSION_INFO CL3IF_GetVersion(void) {
CL3IF_VERSION_INFO info = {1,2,3,4};
return info;
}
}
test.py
import ctypes
class CLIF_VERSION_INFO(ctypes.Structure):
_fields_ = [("majorNumber", ctypes.c_int),
("minorNumber", ctypes.c_int),
("revisionNumber", ctypes.c_int),
("buildNumber", ctypes.c_int)]
def __repr__(self):
return f'CLIF_VERSION_INFO(major={self.majorNumber},minor={self.minorNumber},rev={self.revisionNumber},build={self.buildNumber})'
dll = ctypes.CDLL('./test')
dll.CL3IF_GetVersion.argtypes = ()
dll.CL3IF_GetVersion.restype = CLIF_VERSION_INFO
print(dll.CL3IF_GetVersion())
输出:
CLIF_VERSION_INFO(major=1,minor=2,rev=3,build=4)
我正在使用一个名为 CL3_IF.dll 的 DLL,其文档中将其描述为:
格式:CL3IF_VERSION_INFO CL3IF_GetVersion(void)
参数:—
Return 值: Return此 DLL 的版本。
typedef struct {
INT majorNumber;
INT minorNumber;
INT revisionNumber;
INT buildNumber;
} CL3IF_VERSION_INFO;
说明:该函数获取DLL版本。
我使用了以下 python 代码:
import ctypes
CLP=ctypes.WinDLL('CL3_IF.dll')
class CLIF_VERSION_INFO(ctypes.Structure):
_fields_ = [("majorNumber", ctypes.c_int),
("minorNumber", ctypes.c_int),
("revisionNumber", ctypes.c_int),
("buildNumber", ctypes.c_int)]
CLP.CL3IF_GetVersion(ctypes.c_void_p, CLIF_VERSION_INFO)
当我运行上面的代码时,我得到以下错误:
ArgumentError: argument 1: <class 'TypeError'>: Don't know how to convert parameter 1
我希望能够以可用的形式获取版本信息,并且 dll 的许多其他函数以复杂的结构提供它们的输出。
我将使用的最复杂的函数是 this
如果有人知道我将如何阅读此输出,我将不胜感激。
returned结构是一个return值,不是参数,void
表示没有参数,而c_void_p
表示有void*
参数.确保正确设置 .argtypes
和 .restype
。
另请注意,WinDLL
适用于 32 位 __stdcall
API。将 CDLL
用于 __cdecl
(C 调用约定)API。在 64 位 Python 上两者都可以工作,因为只有一种调用约定,但对于可移植代码,请使用正确的约定。
完整示例如下:
test.cpp
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef int INT;
typedef struct {
INT majorNumber;
INT minorNumber;
INT revisionNumber;
INT buildNumber;
} CL3IF_VERSION_INFO;
extern "C"
{
API CL3IF_VERSION_INFO CL3IF_GetVersion(void) {
CL3IF_VERSION_INFO info = {1,2,3,4};
return info;
}
}
test.py
import ctypes
class CLIF_VERSION_INFO(ctypes.Structure):
_fields_ = [("majorNumber", ctypes.c_int),
("minorNumber", ctypes.c_int),
("revisionNumber", ctypes.c_int),
("buildNumber", ctypes.c_int)]
def __repr__(self):
return f'CLIF_VERSION_INFO(major={self.majorNumber},minor={self.minorNumber},rev={self.revisionNumber},build={self.buildNumber})'
dll = ctypes.CDLL('./test')
dll.CL3IF_GetVersion.argtypes = ()
dll.CL3IF_GetVersion.restype = CLIF_VERSION_INFO
print(dll.CL3IF_GetVersion())
输出:
CLIF_VERSION_INFO(major=1,minor=2,rev=3,build=4)