web-dev-qa-db-ja.com

ctypeバイト配列をバイトに変換します

私はこのように定義したctypes配列を持っています:

buff= (c_ubyte*buff_size)()

バッファをデータでいっぱいにした後、このデータをバイト形式にする必要があります。今、私はそれを次のようにやっています:

buff= [n for n in buff]
buff = ''.join(map(chr, buff))

これに伴う問題は、それを1バイト文字列に戻す前に4バイト(または任意のバイト数)のintに変換することであり、これは多くのCPUを浪費します。

Ctypesバッファを直接バイトに変換するにはどうすればよいですか?元のバッファを保持できないため、とにかくコピーを実行する必要があるため、自分でコピーを保存しようとはしていません。 pythonにはそのようなもののキャスト機能がありますか?

ありがとう。

11
Matt

コピーが必要な場合は、bytearrayを使用できます。

_>>> buff = (c_ubyte * 4)(*[97,98,99,100])
>>> bs = bytearray(buff)
>>> bs
bytearray(b'abcd')
>>> str(bs)
'abcd'
_

編集

bytearrayがない2.6より前のバージョンのPython)の場合、代わりに次のいずれかを使用できます。

  • cast(buff, c_char_p).value
  • buffer(buff)[:]

同じバッファを共有したい場合は、_c_char_配列を作成できます。

_>>> buff2 = (c_char * len(buff)).from_buffer(buff)
>>> buff2.value # string copy
'abcd'
>>> buff2[:] = 'efgh'
>>> buff[:]  # modified original
[101, 102, 103, 104]
_

編集

_from_buffer_クラスメソッドは2.6で追加されました。以前のバージョンでは、castを使用できます。

  • buff2 = cast(buff, POINTER(c_char * len(buff)))[0]

そもそも_c_char_配列を使用していない理由はありますか?数値配列と文字列の両方として使用する必要があるかどうかを理解しています。

補遺:

2番目の方法は、バッファをコピーしないため、より「キャスト」されます。最初のアプローチでは、2回コピーされます。1回目はbytearrayを作成し、もう1回はstrを作成します(bytesは2のstrのエイリアスです。バツ)。しかし、bytearrayには文字列メソッドがあり、必要なのはそれだけかもしれません。これは基本的に3.xbytesの変更可能なバージョンです。

_c_char_はC char型です。配列に乗算すると、現在の_c_ubyte_配列のようなバイトの可変バッファーになります。ただし、Pythonバイト文字列を返すvalueおよびraw記述子があるため、_c_ubyte_よりも便利な場合があります。整数ではなく、1文字のバイト文字列として繰り返されます。

あなたがすることになっていないことは、_c_char_p_--文字データへのポインタ-をPython文字列(関数がそれを変更する場合)から作成することです。Python文字列オブジェクトは不変です。バッファを変更すると奇妙なバグが発生する可能性があります。最近 質問に回答しました そのトピックについて。

16
Eryk Sun