2017-03-07 33 views
2

私はPythonのバイト(b'')として定義したctype.Structureにアクセスしたいと思います。ctypesをバイトに変換するには

正しい方法は分かりませんが、私は他のデバイスにヘッダ(それはアーキテクチャフリーでなければならない)を送る必要があります。

としてだから私は、例えば、それを定義した:

class Header(ctypes.Structure): 
    _pack_ = 2 
    _fields_ = [ 
     ('version', c_uint8), 
     ('additional_options', c_uint8), 
     ('soft_version', c_uint16), 
     ('compilation_time', c_uint8 * 6), 
     ('crc', c_uint16) 
    ] 

は、今私はCRCを計算する必要があります。 versionからcompilation_timeに開始する私はバイトを扱う関数を持っています。

私にとっては、ctypes.Structureをバイト(b ")に変換するか、直接メモリにアクセスして最後の2バイトを変更するだけでOKです。

私はstructを試してみましたが、私は見つけませんでしたプラグマオプション。

答えて

2

struct何をしたいです:

>>> import struct 
>>> fmt = struct.Struct('<BBH6s') 
>>> data = fmt.pack(1,2,3,b'170207') 
>>> data 
b'\x01\x02\x03\x00170207' 
>>> crc = <do your calculation> 
>>> data += struct.pack('<H',crc) 

<手段は、リトルエンディアンパックおよびCのようなパディングバイトを追加しませんでしょう、そう何_pack_は必要ありません。ビッグエンディアンが必要な場合は、代わりに>を使用してください。

私は6sを使用し、正しい長さのバイト文字列を渡しました。代わりに生のバイトを渡す場合は、6Bを使用し、1つの文字列の代わりに6バイトをリストします。

ここにctypesソリューションがあります。私はcrc32を使用しました。なぜなら、デモのためにライブラリで利用可能だったからです。

from ctypes import * 
from binascii import crc32 

class Header(Structure): 
    _pack_ = 2 
    _fields_ = [ 
     ('version', c_uint8), 
     ('additional_options', c_uint8), 
     ('soft_version', c_uint16), 
     ('compilation_time', c_uint8 * 6), 
     ('crc', c_uint32) 
    ] 

h = Header(1,2,3) 
h.compilation_time = (c_uint8 * 6)(*b'ABCDEF') 
b = string_at(addressof(h),sizeof(h)-Header.crc.size) 
print(b) 
h.crc = crc32(b) 
b = string_at(addressof(h),sizeof(h)) 
print(b) 

出力:このソリューションの

b'\x01\x02\x03\x00ABCDEF' 
b'\x01\x02\x03\x00ABCDEF\xe7s\x85\xa6' 
+0

BIG欠点は、読みやすさです。私のヘッダーは128バイトなので、本当に混乱して読めなくなります(ctypesと比較して)。 'H' =' unsigned short'のマシンで何が2番目に** ** = 16ビット? –

+0

@ S.Rあなたは「構造体を試しましたが、私は**プラグマ**オプションを見つけられませんでした」と述べました。構造体をまったく使用したくない場合は、より具体的にしてください。とにかく、ctypesソリューションを表示するように更新されました。 –

+0

@MarekTolonen私の意見では、両方のオプションはPythonコードの残りの部分と同じくらい読みやすくはありません。しかし、私は最終的にネイティブ 'struct'を使用しました。 –

関連する問題