我正在尝试调用返回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
只能达到第一个NULL。
在C中它会是这样的:
while (*sz) {;
doStuff(sz);
sz += lstrlen(sz) + 1;
}
答案 0 :(得分:5)
在发现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
答案 1 :(得分:3)
如果您发布了可运行代码会更容易:为此调用获取合适的卷名有点痛苦。 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)
当我运行这个时,所有列表只包含一个名称,但如果你仔细检查长度,那么它们包含在返回的缓冲区中。