0

I'm trying to figure out how take test_data and pack it into TestInfo

from ctypes import Structure, c_char, c_uint8


class TestInfo(Structure):
    _fields_ = [
        ('version', c_uint8),
        ('lsbyte', c_uint8),
        ('msbyte', c_uint8),
        ('free_space', c_uint8 * 2),
        ('recent_addtime', c_uint8 * 4),
        ('recent_erasetime', c_uint8 * 4),
        ('operation_support', c_uint8)
    ]
test_data = '51 af 01 00 65 f1 52 ff 60 f4 00 c7 60 0a'

It should be packed like this

TestInfo.version = 0x51
TestInfo.lsbyte  = 0xaf
...
...
TestInfo.recent_erasetime = 0xf400c760
TestInfo.operation_support = 0x0a

1 Answer 1

1

You can use the following:

import ctypes as ct

class TestInfo(ct.BigEndianStructure):
    _pack_ = 1
    _fields_ = [('version', ct.c_uint8),
                ('lsbyte', ct.c_uint8),
                ('msbyte', ct.c_uint8),
                ('free_space', ct.c_uint16),
                ('recent_addtime', ct.c_uint32),
                ('recent_erasetime', ct.c_uint32),
                ('operation_support', ct.c_uint8)]

    def __repr__(self):
        return (f'TestInfo(version={self.version:#02x}, lsbyte={self.lsbyte:#02x}, ' \
               f'msbyte={self.msbyte:#02x}, free_space={self.free_space:#04x}, ' \
               f'recent_addtime={self.recent_addtime:#08x}, ' \
               f'recent_erasetime={self.recent_erasetime:#08x}, ' \
               f'operation_support={self.operation_support:#02x})')

test_data = bytes.fromhex('51 af 01 00 65 f1 52 ff 60 f4 00 c7 60 0a')
test_info = TestInfo.from_buffer_copy(test_data)
print(test_info)

Output:

TestInfo(version=0x51, lsbyte=0xaf, msbyte=0x1, free_space=0x65, recent_addtime=0xf152ff60, recent_erasetime=0xf400c760, operation_support=0xa)

Another option is to use the struct and namedtuple modules if not passing this structure to C code.

import struct
from collections import namedtuple

TestInfo = namedtuple('TestInfo','version lsbyte msbyte free_space recent_addtime recent_erasetime operation_support')

test_data = bytes.fromhex('51 af 01 00 65 f1 52 ff 60 f4 00 c7 60 0a')
test_info = TestInfo(*struct.unpack('>BBBHLLB',test_data))
print(test_info)
print(hex(test_info.recent_erasetime))

Output (decimal values are equivalent, printed one to verify):

TestInfo(version=81, lsbyte=175, msbyte=1, free_space=101, recent_addtime=4048748384, recent_erasetime=4093691744, operation_support=10)
0xf400c760
Sign up to request clarification or add additional context in comments.

1 Comment

I'm trying to make my module accept data from a CLI or also from IOCTL so I want to keep it as true to the C alignment (etc) as possible. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.