从python访问C结构

时间:2012-10-27 14:02:37

标签: python c python-3.x structure ctypes

我要创建一个访问windows dll函数的python脚本。我成功地访问了dll及其功能。现在,我有一个c函数

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;

C函数如下

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 Structure DEVINFO中,它包含另一个结构DEVEXTENSION。我如何能够访问DEVEXTENSION错误的成员?

print (devInfo.pDevExtension.szName)

这引发:

AttributeError: 'LP_DEVEXTENSION" object has no attribute szName

2 个答案:

答案 0 :(得分:3)

您的结构声明错误。它应该是:

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))
    ]

当您致电DEVINFO时,您还必须将指针传递给FIOCreateDeviceInfoList()结构。我会这样做:

funcCreateList = lib.FIOCreateDeviceInfoList(byref(devInfo))

正如@eryksun帮助指出的那样,添加

lib.FIOCreateDeviceInfoList.argtypes = [POINTER(DEVINFO)]
在调用FIOCreateDeviceInfoList()之前

将使ctypes执行运行时类型检查。

答案 1 :(得分:0)

告诉ctypes FIOCreateDeviceInfoList的参数类型是指向DEVINFO结构的指针,方法是设置argtypes属性,如下所示:

lib.FIOCreateDeviceInfoList.argtypes = [POINTER(DEVINFO)]