我想通过Ctypes枚举设备,转换问题

I want to enumerate devices via Ctypes,conversion problem

我想用Ctypes来枚举设备,下面的例子是C++语言我不是很擅长转换,下面的代码是我写的一半

我的问题是如何转换这个

//Enumerate through all devices in Set
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i=0;SetupDiEnumDeviceInfo(hDevInfo,i,
    &DeviceInfoData);i++)

https://social.msdn.microsoft.com/forums/windowsdesktop/en-US/43ab4902-75b9-4c5c-9b54-4567c825539f/how-to-enumerate-hardware-devices-by-using-setupdi?forum=vcgeneral

import ctypes as ct
from ctypes import wintypes as w

SetupAPI = ct.WinDLL('SetupAPI')

SetupAPI.SetupDiGetClassDevsW.argtypes = w.LPVOID,w.PWCHAR,w.HWND,w.DWORD
SetupAPI.SetupDiGetClassDevsW.restype = w.HANDLE
SetupAPI.SetupDiEnumDeviceInfo.argtypes = w.HANDLE,w.DWORD,w.HANDLE
SetupAPI.SetupDiEnumDeviceInfo.restype = w.BOOLEAN 

DIGCF_DEFAULT         =  0x00000001  
DIGCF_PRESENT         =  0x00000002
DIGCF_ALLCLASSES      =  0x00000004
DIGCF_PROFILE         =  0x00000008
DIGCF_DEVICEINTERFACE =  0x00000010

ClassGuid = None
Enumerator = None
hwndParent = None
Flags = DIGCF_PRESENT | DIGCF_ALLCLASSES

DeviceInfoSet = None
MemberIndex = None
DeviceInfoData = None

class SP_DEVINFO_DATA(ct.Structure):
    _fields_ = [
                ('cbSize',w.DWORD),
                ('ClassGuid',w.LPVOID),
                ('DevInst',w.DWORD),
                ('Reserved',w.ULONG),
                ]

SP_DEVINFO_DATA = SP_DEVINFO_DATA()

hDevInfo = SetupAPI.SetupDiGetClassDevsW(
                                        ClassGuid,
                                        Enumerator,
                                        hwndParent,
                                        Flags
                                        )


SP_DEVINFO_DATA.cbSize = ct.sizeof(SP_DEVINFO_DATA)

DeviceInfoSet = hex(hDevInfo)
MemberIndex = 1
DeviceInfoData = ct.byref(SP_DEVINFO_DATA)

SetupDiEnumDeviceInfo = SetupAPI.SetupDiEnumDeviceInfo(
                              DeviceInfoSet,
                              MemberIndex,
                              DeviceInfoData
                              )

print(SetupDiEnumDeviceInfo)

这是一个完整的类型安全示例,用于枚举特定设备类型,在本例中为 USB 主机控制器:

import ctypes as ct
from ctypes import wintypes as w
import uuid

SetupAPI = ct.WinDLL('SetupAPI')

# ULONG_PTR is defined as an unsigned integer of the same size as a pointer on the OS, 
# which is ct.ulonglong on 64-bit or ct.ulong on 32-bit.  w.WPARAM happens to follow
# that same definition.
ULONG_PTR = w.WPARAM

# For type safety.  A ctypes function will only accept HDEVINFO not any old HANDLE.
class HDEVINFO(w.HANDLE):
    pass

# A class to initialize and print GUIDs
class GUID(ct.Structure):

    _fields_ = (('Data1', ct.c_ulong),
                ('Data2', ct.c_ushort),
                ('Data3', ct.c_ushort),
                ('Data4', ct.c_ubyte * 8))

    def __repr__(self):
        return f"GUID('{self}')"

    def __str__(self):
        return (f'{{{self.Data1:08x}-{self.Data2:04x}-{self.Data3:04x}-'
                f'{bytes(self.Data4[:2]).hex()}-{bytes(self.Data4[2:]).hex()}}}')

    def __init__(self,guid=None):
        if guid is not None:
            data = uuid.UUID(guid)
            self.Data1 = data.time_low
            self.Data2 = data.time_mid
            self.Data3 = data.time_hi_version
            self.Data4[0] = data.clock_seq_hi_variant
            self.Data4[1] = data.clock_seq_low
            self.Data4[2:] = data.node.to_bytes(6,'big')

PGUID = ct.POINTER(GUID)

# See https://docs.microsoft.com/en-us/windows-hardware/drivers/install/guid-devinterface-usb-host-controller
GUID_DEVINTERFACE_USB_HOST_CONTROLLER = GUID('{3ABF6F2D-71C4-462A-8A92-1E6861E6AF27}')

class SP_DEVINFO_DATA(ct.Structure):

    _fields_ = (('cbSize', w.DWORD), 
                ('ClassGuid', GUID), 
                ('DevInst', w.DWORD), 
                ('Reserved', ULONG_PTR))

    def __repr__(self):
        return f'SP_DEVINFO_DATA(ClassGuid={self.ClassGuid}, DevInst={self.DevInst})'

    # Per docs, the cbSize member must be set to the size of this structure.
    def __init__(self):
        self.cbSize = ct.sizeof(SP_DEVINFO_DATA)

PSP_DEVINFO_DATA = ct.POINTER(SP_DEVINFO_DATA)

SetupAPI.SetupDiGetClassDevsW.argtypes = PGUID, w.PWCHAR, w.HWND, w.DWORD
SetupAPI.SetupDiGetClassDevsW.restype = HDEVINFO
SetupAPI.SetupDiEnumDeviceInfo.argtypes = HDEVINFO, w.DWORD, PSP_DEVINFO_DATA
SetupAPI.SetupDiEnumDeviceInfo.restype = w.BOOL 
SetupAPI.SetupDiDestroyDeviceInfoList.argtypes = HDEVINFO,
SetupAPI.SetupDiDestroyDeviceInfoList.restype = w.BOOL

DIGCF_DEFAULT         =  0x00000001  
DIGCF_PRESENT         =  0x00000002
DIGCF_ALLCLASSES      =  0x00000004
DIGCF_PROFILE         =  0x00000008
DIGCF_DEVICEINTERFACE =  0x00000010

ClassGuid = GUID_DEVINTERFACE_USB_HOST_CONTROLLER
Enumerator = None
hwndParent = None
Flags = DIGCF_DEVICEINTERFACE | DIGCF_PRESENT

devinfo = SP_DEVINFO_DATA()

# Query for the device interface,
# then enumerate them one by one by incrementing a zero-based index
hDevInfo = SetupAPI.SetupDiGetClassDevsW(ClassGuid, Enumerator, hwndParent, Flags)
try:
    MemberIndex = 0
    while SetupAPI.SetupDiEnumDeviceInfo(hDevInfo, MemberIndex, ct.byref(devinfo)):
        print(devinfo)
        MemberIndex += 1
finally:
    SetupAPI.SetupDiDestroyDeviceInfoList(hDevInfo)

输出:

SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=144)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=137)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=17)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=78)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=24)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=98)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=123)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=41)

我的系统有八个 USB 主机控制器,class GUID 匹配: