1

我找到了一个在 python ctypes 中调整数组大小的答案

from ctypes import *

list = (c_int*1)()

def customresize(array, new_size):
    resize(array, sizeof(array._type_)*new_size)
    return (array._type_*new_size).from_address(addressof(array))

list[0] = 123
list = customresize(list, 5)

>>> list[0]
123
>>> list[4]
0

如果我再次调用它:

list = customresize(list, 40)

它给出了错误:

ValueError: Memory cannot be resized because this object doesn't own it

为什么它只适用于您第一次打电话customresize()?我还看到有人发布了另一个答案:

def customresize(array, new_size):
    return (array._type_*new_size).from_address(addressof(array))

customresize()无论您调用多少次,这里都有效。

但它提出了另一个问题,我发现我的 python.exe 在你调整到更大的大小时不会使用更多list的内存,这意味着内存没有分配给调整大小的list. 在没有分配的情况下提供对内存的可访问性是否非常危险?为什么这样ctypes.resize设计?真的是一头雾水。。。。

4

2 回答 2

2

from_address很危险,因为它不能确保您已经分配了正在访问的内存,因此它可能导致您的应用程序崩溃或更糟。此外,它不拥有它指向的内存,因此如果原始所有者被删除,则该内存可以用于其他用途。

这里的一种选择是保留对原始数组的引用:

def customresize(array, new_size):
    base = getattr(array, 'base', array)
    resize(base, sizeof(array._type_)*new_size)
    new_array = (array._type_*new_size).from_address(addressof(base))
    new_array.base = base

另一种更安全的方法是,您可以从旧数组创建一个新数组:

list = (c_int * 5)(*list)
于 2012-07-24T16:39:17.250 回答
1

让我自己总结一下这个问题。但请归功于@ecatmur 和其他人 resize() 函数可用于调整现有 ctypes 对象的内存缓冲区的大小。该函数将对象作为第一个参数,并将请求的大小(以字节为单位)作为第二个参数。但是,调整大小的对象仍然无法访问基于其原始大小的内存缓冲区。解决问题。定义了 3 个不同的函数:

def customresize1(array, new_size):
    resize(array, sizeof(array._type_)*new_size)
    return (array._type_*new_size).from_address(addressof(array))
def customresize2(array, new_size):
    return (array._type_*new_size).from_address(addressof(array))
def customresize3(array, new_size):
    base = getattr(array, 'base', array)
    resize(base, sizeof(array._type_)*new_size)
    new_array = (array._type_*new_size).from_address(addressof(base))
    new_array.base = base

所有函数都返回一个共享原始所有者内存的对象,该对象不拥有内存并且无法调整大小(例如,在 中给出错误customresize1

customresize2确实返回一个调整大小的数组,但请记住 from_address 不会为调整大小分配内存..

customresize3保留拥有内存的基础对象的记录,但返回的对象不是内存的所有者

由于 python 动态分配它的内存和垃圾收集,所以,如果你想调整某些东西的大小,只需重做大小就可以了。例如。:

list = (c_int * NEW_SIZE)()

或者您可能希望保留原始值:

list = (c_int * NEW_SIZE)(*list)
于 2012-07-24T18:52:10.700 回答