在不使用额外内存的情况下比较ctypes数组

3 投票
1 回答
2231 浏览
提问于 2025-04-18 16:13

我有两个很大的 ctypes 数组,我想比较它们,但不想占用额外的内存。直接比较是行不通的:

>>> a = ctypes.create_string_buffer(b'1'*0x100000)
>>> b = ctypes.create_string_buffer(b'1'*0x100000)
>>> a == b
False

使用 valueraw 属性会在内存中创建数组的一个副本。

memoryview 来包裹这两个缓冲区会让速度变得非常慢。

在 Windows 系统上,一个可能的解决办法是直接使用 msvcrt.memcmp,但有没有更符合 Python 风格或者跨平台的方法呢?

1 个回答

3

你可以通过 ctypes.util.find_library 这个方法,以不依赖平台的方式找到特定的C语言库。库里面提供的功能可以根据需要使用。

这样,你可以通过以下方式来比较数组:

libc_name = ctypes.util.find_library("c")
libc = ctypes.CDLL(libc_name)

libc.memcmp.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t)

len(a) == len(b) and libc.memcmp(a, b, len(a)) == 0

需要注意的是,如果调用这些函数时出错,它们会非常严格。如果你设置了函数的参数类型,函数会在调用库函数之前检查这些参数。

如果你想用纯Python的方式来比较数组,而且不想占用太多额外的内存,可以使用下面的方法。这个方法使用了生成器,逐个比较每个元素,而不是把整个数组复制到其他地方再进行比较。

len(a) == len(b) and all(x == y for x, y in zip(a,b))

不过,这种方法的缺点是会创建很多小的对象,每个对象占用的内存不多,但这样会增加计算的开销(主要是CPU的负担,而不是内存)。

撰写回答