给定一个定义了大量结构的C头文件和一个原始十六进制字符串,我想将字符串解析为相应的C结构。
我已经研究过struct.unpack()来完成这个,但是我无法想出一种自动派生格式字符串的方法(这是可取的,因为这个头文件经常被更新)。
是否找到了为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)
使用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