Michal
Michal

Reputation: 33

Python equivalent of C struct (porting app form C to python)

I'm porting a simple bluetooth app, which sends "magic" packet on L2Cap protocol to bluetooth device..

I have a problem with converting struct object in C to python equivalent..

In 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;

and then in app it's used like that:

        /* 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));

Can you point me out how to construct same packet/stuct-like structure using python?

I know I will probably need to use ctypes and create "empty" class, but how to get all this together?

Upvotes: 3

Views: 2198

Answers (2)

Michael F
Michael F

Reputation: 40832

You can go about it with the struct module to pack values into a byte string, for example:

>>> 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'

Alternatively, you can use ctypes.Structure to define a class that will be representing your structure. It has the advantage of being easier to use with Python code, but you have to take into account alignment and padding issues and resolve them yourself (perhaps with struct).

Upvotes: 3

Simon Bergot
Simon Bergot

Reputation: 10582

If your goal is to group a set of key/value in an object, you may use dict or namedtuple.

a dict would be:

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

access: CFGBTFRAME['type']

with namedtuple:

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

see http://docs.python.org/library/collections.html#collections.namedtuple for more information about namedtuple.

Upvotes: 0

Related Questions