1

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

もう一度呼び出すと:

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))

herecustomresize()は、何度呼び出しても機能します。

listしかし、別の質問が発生します。サイズを大きくしても、python.exeがより多くのメモリを使用しないことがわかりました。つまり、サイズ変更されたlist. 割り当てなしでメモリにアクセスできるようにすることは非常に危険ですか? なぜctypes.resizeこのように設計されているのですか?本当に迷う……。

4

2 に答える 2

2

from_addressアクセスしているメモリが割り当てられていることを保証しないため危険です。そのため、アプリケーションがクラッシュしたり、さらに悪化したりする可能性があります。さらに、それが指すメモリを所有していないため、元の所有者が削除された場合、メモリは別の目的で再利用される可能性があります。

ここでの 1 つのオプションは、元の配列への参照を保持することです。

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 オブジェクトのメモリ バッファのサイズを変更できます。この関数は、オブジェクトを最初の引数として受け取り、要求されたサイズ (バイト単位) を 2 番目の引数として受け取ります。ただし、サイズ変更されたオブジェクトは、元のサイズに基づいてメモリ バッファーへのアクセスが制限されます。この問題を解決するために。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 に答える