Python 调整(收缩)ctypes数组的大小

Python 调整(收缩)ctypes数组的大小,python,arrays,resize,ctypes,Python,Arrays,Resize,Ctypes,假设我有一个10元素的数组: from ctypes import * arr = c_float * 10 ,我想把它缩小到5个元素。我试过这样做: resize(arr, sizeof(c_float) * 5) arr = (c_float * 5).from_address(addressof(arr)) 但是我得到了一个ValueError:最小大小是XXX异常,这意味着我不能收缩内存,只能增加内存。如果我真的想,有没有可能用一个聪明的黑客来克服这个限制?这似乎很好: >&g

假设我有一个10元素的数组:

from ctypes import *
arr = c_float * 10
,我想把它缩小到5个元素。我试过这样做:

resize(arr, sizeof(c_float) * 5)
arr = (c_float * 5).from_address(addressof(arr))

但是我得到了一个
ValueError:最小大小是XXX
异常,这意味着我不能收缩内存,只能增加内存。如果我真的想,有没有可能用一个聪明的黑客来克服这个限制?

这似乎很好:

>>> float_10 = c_float * 10
>>> float_5 = c_float * 5
>>> a1 = float_10(range(10))
>>> a2 = float_5.from_address(addressof(a1))
>>> print list(a1)
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
>>> print list(a2)
[0.0, 1.0, 2.0, 3.0, 4.0]

编辑:这实际上不会调整原始列表的大小,而且
addressof(a1)
将等于
addressof(a2)
,因此列表中未使用的位将保留在内存中…

本机C函数
realloc
允许内存收缩。这可能不安全,但实际上会在调整阵列大小后释放内存:

from ctpyes import *
clib = CDLL("libc.so.6")

bigarr = (c_float * 10)(*range(10)) # some data
smallarr = (c_float * 5).from_buffer(bigarr) # no copies here

# free unneeded memory
clib.realloc(bigarr, sizeof(smallarr))

# finally, delete the bigarr python object because occasional
# use of its truncated elements may cause segfault.
del bigarr
我用100000浮点数组测试了它,看看内存是否真的被释放了


UPD:正如AKX所指出的(这里也包括:),这种方法不能保证
realloc
的返回将指向与以前使用的原始数组相同的内存位置,尽管在我的实践中总是这样

这就是我现在所拥有的,我保存了
实际大小
,并且只在增长时调整大小。是的,我认为没有任何安全的方法可以在不复制数据的情况下缩小数组…@GiovanniFunchal,这难道不能回答您的问题吗?您不是应该查看
realloc
的返回值,看看它在调整缓冲区大小时是否移动了缓冲区吗?此外,我想Python甚至不能保证使用libc内存分配器(可以使用jemalloc或其他什么),因此
realloc
可能会对缓冲区造成绝对的破坏。。。耸耸肩:)@AKX,我对此进行了多次测试,
realloc
始终返回与bigarr和smallarr的
addressof
相同的值。如果无法调整原始数组的大小,它将返回另一个指针。我认为在不移动的情况下缩小数组应该是可行的,因为不需要更多的内存。是的,但是
realloc
的规范说它将返回新的位置,所以允许它这样做。@AKX,你是对的。出于好奇,您是否知道
clib.realloc
会在收缩时移动数据?