2017-03-07 90 views
2

我想訪問ctype.Structure,我已經定義了Python中的字節(b'')。如何將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'')或直接訪問內存並更改最後兩個字節即可。

我曾嘗試使用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) 

<手段收拾little-endian的,不會添加填充字節像C會,所以沒有_pack_是必要的。如果您需要big-endian,請改爲使用>

我使用了6s,併爲您的時間傳遞了正確長度的字節字符串。如果要傳遞原始字節,請使用6B,並列出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缺點是可讀性。我的頭文件長度爲128bytes,所以它會真的搞砸並且不可讀(與ctypes相比)。 第二個什麼機器哪裏'H' ='無符號短'**!= ** 16位? –

+0

@ S.R您提到「嘗試使用struct但我沒有找到** pragma **選項」。如果你根本不想使用struct,那麼更具體一些。無論如何,更新爲顯示ctypes解決方案。 –

+0

@MarekTolonen在我看來,這兩個選項都不如Python代碼的其餘部分可讀。但我最終使用了本地'struct'。 –