2013-07-09 92 views
0

給定一個定義了很多結構的C頭文件和一個原始的十六進制字符串,我想將該字符串解析爲相應的C結構。我已經研究過struct.unpack()來完成這個任務,但我無法想出一種方法來自動導出格式字符串(這是可取的,因爲這個頭文件經常更新)。將字節串解析爲C結構

找到一種方法來爲struct.unpack()生成格式字符串的正確方法?還是有更簡單的方法來解析十六進制字符串到C結構?

import struct 

''' 
Example structure: 

typedef struct { 
    struct { 
    uint8_t a_flag:1; 
    uint8_t b_flag:1; 
    uint8_t c_flag:1; 
    uint8_t d_flag:1; 
    uint8_t unused:3; 
    uint8_t e_flag:1; 
    } PACKED flag_byte_0; 

    struct { 
    uint8_t unused:6; 
    uint8_t f_flag:1; 
    uint8_t g_flag:1; 
    } PACKED flag_byte_1; 

struct { 
    uint8_t unused:5; 
    uint8_t h_flag:1; 
    uint8_t i_flag:1; 
    uint8_t j_flag:1; 
} PACKED flag_byte_2; 

struct { 
    uint8_t unused:2; 
    uint8_t k_flag; 
    uint8_t l_flag:1; 
    uint8_t unused_2:4; 
} PACKED flag_byte_3; 

    uint16_t field_a; 
    uint16_t field_b; 
    uint32_t field_c:24; 
    uint32_t field_d:8; 
} PACKED struct_example; 
''' 

if __name__ == '__main__': 
    hex_string = '\x10\x08\x00\x00\x3d\x00\x08\xd7\x90\x00\x00\x0a' 
    format_string = 'BBBBHHI' 
    struct.unpack(format_string, hex_string) 
    # returns (16, 8, 0, 0, 61, 55048, 167772304) 
    # really want: 
    # a_flag:1 
    # g_flag:1 
    # ... 
    # field_a: 0x3d00 
    # etc... 
+0

您可以在您的文章的一些樣品?請同時添加您迄今爲止所做的任何嘗試,至少證明您嘗試了什麼。 –

+0

你打算在Python中處理結果結構還是隻是將它傳遞給C函數?在後一種情況下,不需要拆包。 –

+0

@ nikolay-polivanov解析後的結果將在Python中處理。主要目標是以人類可讀格式顯示結果 –

回答

0

使用cffi

from cffi import FFI 

ffi = FFI() 
ffi.cdef(''' 
typedef struct { 
    struct { 
    uint8_t a_flag:1; 
    uint8_t b_flag:1; 
    uint8_t c_flag:1; 
    uint8_t d_flag:1; 
    uint8_t unused:3; 
    uint8_t e_flag:1; 
    } flag_byte_0; 

    struct { 
    uint8_t unused:6; 
    uint8_t f_flag:1; 
    uint8_t g_flag:1; 
    } flag_byte_1; 

    struct { 
    uint8_t unused:5; 
    uint8_t h_flag:1; 
    uint8_t i_flag:1; 
    uint8_t j_flag:1; 
    } flag_byte_2; 

    struct { 
    uint8_t unused:2; 
    uint8_t k_flag:1; 
    uint8_t l_flag:1; 
    uint8_t unused_2:4; 
    } flag_byte_3; 

    uint16_t field_a; 
    uint16_t field_b; 
    uint32_t field_c:24; 
    uint32_t field_d:8; 
} struct_example; 
''') 


data = '\x10\x08\x00\x00\x3d\x00\x08\xd7\x90\x00\x00\x0a' 
buf = ffi.new('char[]', data) 
st = ffi.cast('struct_example*', buf) 

print st.flag_byte_0.a_flag 
print st.flag_byte_1.g_flag 
print st.flag_byte_2.h_flag 
print st.flag_byte_2.i_flag 
print st.flag_byte_2.j_flag 
print st.flag_byte_3.k_flag 
print st.flag_byte_3.l_flag 
print st.field_a 
print st.field_b 
print st.field_c 
print st.field_d