2013-07-09 62 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