代码之家  ›  专栏  ›  技术社区  ›  grawity_u1686

python ctypes-如何处理字符串数组

  •  2
  • grawity_u1686  · 技术社区  · 16 年前

    我试图调用一个返回 a NULL-terminated array of NULL-terminated strings .

    kernel32 = ctypes.windll.kernel32
    buf = ctypes.create_unicode_buffer(1024)
    length = ctypes.c_int32()
    if kernel32.GetVolumePathNamesForVolumeNameW(ctypes.c_wchar_p(volume),
        buf, ctypes.sizeof(buf), ctypes.pointer(length)):
        ## ???
    

    换言之:

    buf = ctypes.create_unicode_buffer(u'Hello\0StackOverflow\0World!\0')
    

    如何访问 全部的 内容 buf 作为一个python列表? buf.value 只达到第一个空值。

    在C语言中,它是这样的:

    while (*sz) {; 
        doStuff(sz);
        sz += lstrlen(sz) + 1;
    }
    
    2 回复  |  直到 16 年前
        1
  •  5
  •   grawity_u1686    16 年前

    发现后 ctypes.wstring_at() ctypes.addressof() 我得到了这个:

    def wszarray_to_list(array):
        offset = 0
        while offset < ctypes.sizeof(array):
            sz = ctypes.wstring_at(ctypes.addressof(array) + offset*2)
            if sz:
                yield sz
                offset += len(sz)+1
            else:
                break
    
        2
  •  3
  •   Duncan    16 年前

    如果您发布了可运行的代码,就更容易了:为此调用获取合适的卷名有点麻烦。 buf 是包含 length 字符。最后两个字符为空,因此忽略它们,使用 ''.join() 对空字符进行拆分。

    import ctypes
    kernel32 = ctypes.windll.kernel32
    
    def volumes():
        buf = ctypes.create_unicode_buffer(1024)
        length = ctypes.c_int32()
        handle = kernel32.FindFirstVolumeW(buf, ctypes.sizeof(buf))
        if handle:
            yield buf.value
            while kernel32.FindNextVolumeW(handle, buf, ctypes.sizeof(buf)):
                yield buf.value
            kernel32.FindVolumeClose(handle)
    
    def VolumePathNames(volume):
        buf = ctypes.create_unicode_buffer(1024)
        length = ctypes.c_int32()
        kernel32.GetVolumePathNamesForVolumeNameW(ctypes.c_wchar_p(volume),
            buf, ctypes.sizeof(buf), ctypes.pointer(length))
        return ''.join(buf[:length.value-2]).split('\0')
    
    for volume in volumes():
        print volume
        print VolumePathNames(volume)
    

    当我运行这个命令时,所有的列表只包含一个单一的名称,但是如果您仔细检查长度,那么它们就包含在返回的缓冲区中。