【问题标题】:Resize ctypes array调整 ctypes 数组的大小
【发布时间】:2010-10-29 11:53:10
【问题描述】:

我想调整一个 ctypes 数组的大小。如您所见, ctypes.resize 无法正常工作。我可以编写一个函数来调整数组的大小,但我想知道一些其他的解决方案。也许我错过了一些 ctypes 技巧,或者我只是使用了错误的调整大小。 c_long_Array_0 这个名字似乎告诉我这可能不适用于调整大小。

>>> from ctypes import *
>>> c_int * 0
<class '__main__.c_long_Array_0'>
>>> intType = c_int * 0
>>> foo = intType()
>>> foo
<__main__.c_long_Array_0 object at 0xb7ed9e84>
>>> foo[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: invalid index
>>> resize(foo, sizeof(c_int * 1))
>>> foo[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: invalid index
>>> foo
<__main__.c_long_Array_0 object at 0xb7ed9e84>
>>> sizeof(c_int * 0)
0
>>> sizeof(c_int * 1)
4

编辑:也许可以使用类似的东西:

>>> ctypes_resize = resize
>>> def resize(arr, type):
...     tmp = type()
...     for i in range(len(arr)):
...         tmp[i] = arr[i]
...     return tmp
...     
... 
>>> listType = c_int * 0
>>> list = listType()
>>> list = resize(list, c_int * 1)
>>> list[0]
0
>>> 

但是传递类型而不是大小是很难看的。它为它的目的而工作,就是这样。

【问题讨论】:

  • 斯科特,我忘了一件事。我认为如果你的数组像我们正在做的那样被初始化(没有分配一个块,让 ctypes 去做)那么你需要在新的 ctypes 对象中保留对原始对象的引用,因为我认为内存在第一次被释放时对象死亡。所以你需要做“if hasattr(array,"original"), newarray.original = array.original, else newarray.original = array”。然后垃圾收集器将丢弃原始数组,从而释放块。如果您需要帮助,请在 cmets 框中询问。
  • 明白了。我遇到了一个问题,我无法在 ctypes 结构中调整 field 成员的大小。关于内存不被拥有的东西或其他东西。没什么大不了的。
  • 好的,我想我遇到了 gc 问题:python: Modules/gcmodule.c:241: update_refs: Assertion `gc->gc.gc_refs == (-3)' failed。
  • @Scott:您无法调整单个字段的大小,因为所有内存都由主结构对象处理。你应该做的是自己手动分配内存,比如 create_buffer ,然后创建一个析构函数来使用 del 方法释放它。没见过那个python gc错误,你是怎么得到的?
  • 是的,我想出了如何处理内存问题。没什么大不了的。我还不确定我是如何让它抛出这个错误的。我有很多代码要挖掘。我将一堆 C 代码移植到 Python 上,所以问题出在大海捞针上。找到后我会通知你的。

标签: python ctypes


【解决方案1】:
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

【讨论】:

  • 谢谢。我很高兴我问了。我没想到会有答案。 :)
  • 我想我是这里为数不多的 ctypes 专家之一。奇怪的是,我只写了几个 c/python 绑定,几乎没有使用 pyrex/boost/regular 模块的经验。
  • 让我问你这个。我可以像 C 指针一样使用 ctypes 指针吗?就像用加法或减法遍历一个字符数组一样?
  • 是的。 (通知似乎被破坏了)。 intptr = POINTER(c_int)() intptr[0] intptr[234] 等
  • 我在使用这种方法时遇到了缓冲区损坏。示例:list = (c_size_t * 1)(42); list2 = customresize(list, 10); print(list2[0]); list = None; print(list2[0]) 导致输出 42140255071020176。我认为问题归结为_b_needsfree_listlist2 上都为1,所以当list 被删除时,它现在释放实际上属于list2 的缓冲区。我现在的解决方法是创建一个新数组并将元素复制过来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-10
  • 2011-11-10
  • 2021-10-01
  • 2014-01-22
  • 2021-05-05
相关资源
最近更新 更多