从python访问C结构
我将创建一个python脚本来访问windows dll函数。我成功地访问了dll及其函数。现在,我有一个c函数从python访问C结构,python,c,python-3.x,structure,ctypes,Python,C,Python 3.x,Structure,Ctypes,我将创建一个python脚本来访问windows dll函数。我成功地访问了dll及其函数。现在,我有一个c函数 FIOSCR331_API int FIOCreateDeviceInfoList (PDEVINFO pDevInfoSet) 问题在于PDEVINFO结构。我必须用python创建一个结构并访问该结构 C结构如下所示 typedef struct tagDEVINFO { char szDeviceName[MAX_PATH];
FIOSCR331_API int FIOCreateDeviceInfoList (PDEVINFO pDevInfoSet)
问题在于PDEVINFO
结构。我必须用python创建一个结构并访问该结构
C结构如下所示
typedef struct tagDEVINFO
{
char szDeviceName[MAX_PATH];
char szPCSCName[MAX_PATH];
BOOL bPassedFilter;
BOOL bUpdatePassed;
DWORD dwUpdateOrder;
DWORD dwPnP_ID;
DWORD dwFWVersion;
PDEVEXTENSION pDevExtension;
} DEVINFO, *PDEVINFO;
FIOSCR331_API int FIOCreateDeviceInfoList (PDEVINFO pDevInfoSet)
{
int nFIOStatus;
do
{
if ( NULL == pDevInfoSet )
{
printf("this is inside C code\n");
nFIOStatus = IDS_GENERIC_ERROR; //(200)
break;
}
else
printf ("\n%s ",pDevInfoSet->szPCSCName);
}while(false);
}
C函数如下所示
typedef struct tagDEVINFO
{
char szDeviceName[MAX_PATH];
char szPCSCName[MAX_PATH];
BOOL bPassedFilter;
BOOL bUpdatePassed;
DWORD dwUpdateOrder;
DWORD dwPnP_ID;
DWORD dwFWVersion;
PDEVEXTENSION pDevExtension;
} DEVINFO, *PDEVINFO;
FIOSCR331_API int FIOCreateDeviceInfoList (PDEVINFO pDevInfoSet)
{
int nFIOStatus;
do
{
if ( NULL == pDevInfoSet )
{
printf("this is inside C code\n");
nFIOStatus = IDS_GENERIC_ERROR; //(200)
break;
}
else
printf ("\n%s ",pDevInfoSet->szPCSCName);
}while(false);
}
现在是我实现的Python代码
class DEVINFO(Structure):
_fields_ = [("szDeviceName",c_char_p),
("szPCSCName",c_char_p),
("bPassedFilter",c_bool),
("bUpdatePassed",c_bool),
("dwUpdateOrder",c_ulong),
("dwPnp_ID",c_ulong),
("dwFWVersion",c_ulong),
("pDevExtention",DEVEXTENSION)]
lib = cdll.LoadLibrary('libFIOXXXXX.dll')
print (lib)
devInfo = DEVINFO()
devInfo.szPCSCName = c_char_p(b"this is test")
if devInfo is None:
print("hi")
else:
print("britto")
funcCreateList = lib.FIOCreateDeviceInfoList(devInfo)
print (funcCreateList)
我得到的结果是
britto
this is inside C code
200
问题是代码总是处于NULL状态,即devInfo为NULL。为什么呢
新添加的
在上面的python结构DEVINFO中,它包含另一个结构DEVEXTENSION。如何访问DEVEXTENSION错误的成员
print (devInfo.pDevExtension.szName)
这引发了:
AttributeError: 'LP_DEVEXTENSION" object has no attribute szName
通过如下设置
argtypes
属性,告诉ctypesfiocreateDeviceInfo列表的参数类型是指向DeviceInfo结构的指针:
lib.FIOCreateDeviceInfoList.argtypes = [POINTER(DEVINFO)]
您的结构声明是错误的。应该是:
class DEVINFO(Structure):
_fields_ = [
("szDeviceName", c_char*wintypes.MAX_PATH),
("szPCSCName", c_char*wintypes.MAX_PATH),
("bPassedFilter", wintypes.BOOL),
("bUpdatePassed", wintypes.BOOL),
("dwUpdateOrder", wintypes.DWORD),
("dwPnp_ID", wintypes.DWORD),
("dwFWVersion", wintypes.DWORD),
("pDevExtension", POINTER(DEVEXTENSION))
]
调用fiocreateDeviceInfo()
时,还必须传递指向DEVINFO
结构的指针。我会这样做:
funcCreateList = lib.FIOCreateDeviceInfoList(byref(devInfo))
正如@eryksun有益地指出的,添加
lib.FIOCreateDeviceInfoList.argtypes = [POINTER(DEVINFO)]
调用fiocreateDeviceInfo()之前,
将使ctypes
执行运行时类型检查。设置为类型安全的lib.fiocreateDeviceInfo.argtypes=[指针(设备信息)]
@eryksun将应用运行时类型检查吗?是:ctypes.ArgumentError:参数1::应为LP\u DEVINFO实例,而不是str
。这比一个错误要好。@eryksun谢谢。我没有考虑过。但是你说得很好。@Britto:注意,这会在为结构分配的内存中创建内联字符数组。不要用c_char_p
设置值;例如,只需使用devInfo.szPCSCName=b“这是一个测试”
。\u ctypes.CField
负责将字节复制到结构中。对于10-29的后续问题,请使用devInfo.pDevExtension[0].szName
或devInfo.pDevExtension.contents.szName
。