0

多くの構造が定義された C ヘッダー ファイルと生の 16 進文字列が与えられた場合、その文字列を対応する C 構造に解析したいと思います。

これを達成するために struct.unpack() を調べましたが、フォーマット文字列を自動的に導出する方法を思いつくことができませんでした (このヘッダー ファイルは頻繁に更新されるため、これは望ましいことです)。

struct.unpack() のフォーマット文字列を生成する方法を見つけることは正しいアプローチですか? または、16 進文字列を 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...
4

1 に答える 1

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
于 2013-07-09T18:19:59.863 に答える