Python中C结构的等效实现(将应用程序从C移植到Python)

3 投票
2 回答
2176 浏览
提问于 2025-04-17 02:34

我正在移植一个简单的蓝牙应用程序,这个程序通过L2Cap协议向蓝牙设备发送“魔法”数据包。

我遇到了一个问题,就是如何把C语言中的结构体对象转换成Python中的对应结构。

在C语言中:

/* command types */
#define CFGBT_TYPE_SETREQ           0x00
#define CFGBT_TYPE_SETRES           0x01
#define CFGBT_TYPE_GETREQ           0x02
#define CFGBT_TYPE_GETRES           0x03

/* varid types */
#define CFG_VARIDT_UINT16                   0x0000
#define CFG_VARIDT_UINT32                   0x1000
#define CFG_VARIDT_STRING16                 0x2000

typedef struct {
    uint8_t      type, status;
    uint16_t     varid;
    uint8_t      value[16];
} __attribute__((packed)) CFGBTFRAME;

static CFGBTFRAME c;

然后在应用程序中是这样使用的:

        /* set up */
    c.type = CFGBT_TYPE_GETREQ;
    c.varid = strtol(argv[3], NULL, 0);
    c.status = 0;
    memset(c.value, 0, 16);
    /* send frame */
    write(s, &c, sizeof(c));

你能告诉我如何用Python构建一个相同的数据包或类似结构吗?

我知道我可能需要使用ctypes,并创建一个“空”的类,但我该如何把这些结合起来呢?

2 个回答

0

如果你的目标是把一组键值对放在一个对象里,你可以使用 dict(字典)或者 namedtuple(命名元组)。

用字典的方式可以这样写:

CFGBTFRAME = {
    'type' : myType,
    'status' : ...
}

访问字典里的值可以用:CFGBTFRAME['type']

如果用命名元组的话,可以这样:

from collections import namedtuple
CFGBTFRAME = namedtuple('CFGBTFRAME', ['type', 'status', ...])
c = CFGBTFRAME()
c.type = myType

想了解更多关于命名元组的信息,可以查看这个链接:http://docs.python.org/library/collections.html#collections.namedtuple

3

你可以使用 struct 模块把一些值打包成字节串,举个例子:

>>> import struct
>>> type, status, varid, value = 1, 0, 16, b'Hello'
>>> buffer = struct.pack('>BBH16s', type, status, varid, value)
>>> buffer
b'\x01\x00\x00\x10Hello\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

另外,你也可以用 ctypes.Structure 来定义一个类,这个类用来表示你的结构。这样做的好处是用起来更方便,但你需要注意对齐和填充的问题,这些问题需要你自己解决(可能需要用到 struct)。

撰写回答