Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从python访问C结构_Python_C_Python 3.x_Structure_Ctypes - Fatal编程技术网

从python访问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];

我将创建一个python脚本来访问windows dll函数。我成功地访问了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;
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
属性,告诉ctypes
fiocreateDeviceInfo列表的参数类型是指向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