ctypes from buffer - Python

Antonio Rafael da Silva Filho

I'm using ctypes to convert from a binary data buffer

log = DataFromBuffe.from_buffer(buffer)

in my class i have

class DataFromBuffe(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
        ('id', ctypes.c_char * 1),
        ('name', ctypes.c_char * 30),
        ('value', ctypes.c_double),
        ('size', ctypes.c_uint16),
        ('date', type(datetime.datetime))
        ]

But I have two problems?

1 - How can I work with datetime? Fild 'date' is not working.

2 - Field 'size', for some reason is BigEndian. Is it possible change structure just for this field?

Neitsa

1 - How can I work with datetime? Fild 'date' is not working.

Your date field must be a ctypes type (or a type inheriting from a ctypes type). This means you have to find a way to express a date as a number (int, float, double, whatever you want, but it can not be a non-ctypes python type).

In this example I used the well known Unix Epoch (which can be represented on a ctypes.c_uint32)

class DataFromBuffer(ctypes.LittleEndianStructure):
    _pack_ = 1
    _fields_ = [
        ('id', ctypes.c_char * 1),
        ('name', ctypes.c_char * 30),
        ('value', ctypes.c_double),
        ('size', ctypes.c_uint16),
        ('date', ctypes.c_uint32),  # date as a 32-bit unsigned int.
    ]

# snip

    now_date_time = datetime.datetime.now()
    now_int = int(now_date_time.timestamp())  # now as an integer (seconds from the unix epoch)
    print(f"Now - datetime: {now_date_time!s}; int: {now_int}")

    test_buffer = (b"A" + # id
        # snip
        now_int.to_bytes(4, "little")  # date
    )

As for the conversion to a datetime, I simply added a function member to the structure so it can convert the date (a ctypes.c_uint32) to a datetime:

    def date_to_datetime(self) -> datetime.datetime:
        """Get the date field as a python datetime.
        """
        return datetime.datetime.fromtimestamp(self.date)

2 - Field 'size', for some reason is BigEndian. Is it possible change structure just for this field?

No it's not possible. A possible way is to have a function or property to access the field as you want it to be (performing some sort of conversion under the hood):

    def real_size(self) -> int:
        """Get the correct value for the size field (endianness conversion).
        """
        # note: there multiple way of doing this: bytearray.reverse() or struct.pack and unpack, etc.
        high = self.size & 0xff
        low = (self.size & 0xff00) >> 8
        return high | low

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import ctypes
import math
import datetime

class DataFromBuffer(ctypes.LittleEndianStructure):
    _pack_ = 1
    _fields_ = [
        ('id', ctypes.c_char * 1),
        ('name', ctypes.c_char * 30),
        ('value', ctypes.c_double),
        ('size', ctypes.c_uint16),
        ('date', ctypes.c_uint32),
    ]

    def date_to_datetime(self) -> datetime.datetime:
        """Get the date field as a python datetime.
        """
        return datetime.datetime.fromtimestamp(self.date)

    def real_size(self) -> int:
        """Get the correct value for the size field (endianness conversion).
        """
        # note: there multiple way of doing this: bytearray.reverse() or struct.pack and unpack, etc.
        high = self.size & 0xff
        low = (self.size & 0xff00) >> 8
        return high | low

if __name__ == '__main__':
    name = b"foobar"
    now_date_time = datetime.datetime.now()
    now_int = int(now_date_time.timestamp())  # now as an integer (seconds from the unix epoch)
    print(f"Now - datetime: {now_date_time!s}; int: {now_int}")

    test_buffer = (b"A" + # id
        name + (30 - len(name)) * b"\x00" +  # name (padded with needed \x00)
        bytes(ctypes.c_double(math.pi)) +  # PI as double
        len(name).to_bytes(2, "big") +  # size (let's pretend it's the name length)
        now_int.to_bytes(4, "little")  # date (unix epoch)
    )

    assert ctypes.sizeof(DataFromBuffer) == len(test_buffer)

    data = DataFromBuffer.from_buffer(bytearray(test_buffer))
    print(f"date: {data.date}; as datetime: {data.date_to_datetime()}")
    print(f"size: {data.size} ({data.size:#x}); real size: {data.real_size()} ({data.real_size():#x})")

output:

Now - datetime: 2019-07-31 14:52:21.193023; int: 1564577541
date: 1564577541; as datetime: 2019-07-31 14:52:21
size: 1536 (0x600); real size: 6 (0x6)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

python ctypes how to write string to given buffer

From Dev

Python ctypes passing string pointer / buffer

From Dev

How can I read back from a buffer using ctypes?

From Dev

Python ctypes: how to define a callback having a buffer pointer and a length in argument?

From Dev

Python `ctypes` - How to copy buffer returned by C function into a bytearray

From Dev

Python packet sniffer using ctypes crashes when copying socket buffer

From Dev

Python 3.5 - ctypes - create string buffer for Citect API

From Dev

edit the buffer of a Ctypes structure

From Dev

ctypes string buffer in scope

From Dev

Forcing EnumChildWindows to use a global buffer, rather than a local buffer (Python ctypes)

From Dev

Calling CPP function from python ctypes

From Dev

Pass FILE * into function from Python / ctypes

From Dev

Debug C-library from Python (ctypes)

From Dev

Passing struct from C to Python with ctypes

From Dev

Passing audio data from Python to C with ctypes

From Dev

Sending a Polynomial to PARI/GP from Python (ctypes)

From Dev

Python cannot receive the result from cuda ctypes

From Dev

Get image from a fingerprint using Python and Ctypes

From Dev

Ctypes - How to parser buffer content?

From Dev

Python 2.6 read from buffer

From Dev

Python read data from Buffer

From Dev

Write buffer in C which is allocated in python using ctypes, and read back again in python

From Dev

ctypes.Structure.from_buffer_copy doesn't check \0 for c_char-type

From Dev

Python 3 ctypes call to a function that needs an indirect reference to a buffer through another structure

From Dev

How to print contents of ctypes string buffer

From Dev

Pass a pickle buffer from Node to Python

From Dev

Python, How to get an image from a Buffer/stream

From Dev

Buffer.from(<string>, 'hex') equivalent in Python

From Dev

Returning a C array from a C function to Python using ctypes

Related Related

  1. 1

    python ctypes how to write string to given buffer

  2. 2

    Python ctypes passing string pointer / buffer

  3. 3

    How can I read back from a buffer using ctypes?

  4. 4

    Python ctypes: how to define a callback having a buffer pointer and a length in argument?

  5. 5

    Python `ctypes` - How to copy buffer returned by C function into a bytearray

  6. 6

    Python packet sniffer using ctypes crashes when copying socket buffer

  7. 7

    Python 3.5 - ctypes - create string buffer for Citect API

  8. 8

    edit the buffer of a Ctypes structure

  9. 9

    ctypes string buffer in scope

  10. 10

    Forcing EnumChildWindows to use a global buffer, rather than a local buffer (Python ctypes)

  11. 11

    Calling CPP function from python ctypes

  12. 12

    Pass FILE * into function from Python / ctypes

  13. 13

    Debug C-library from Python (ctypes)

  14. 14

    Passing struct from C to Python with ctypes

  15. 15

    Passing audio data from Python to C with ctypes

  16. 16

    Sending a Polynomial to PARI/GP from Python (ctypes)

  17. 17

    Python cannot receive the result from cuda ctypes

  18. 18

    Get image from a fingerprint using Python and Ctypes

  19. 19

    Ctypes - How to parser buffer content?

  20. 20

    Python 2.6 read from buffer

  21. 21

    Python read data from Buffer

  22. 22

    Write buffer in C which is allocated in python using ctypes, and read back again in python

  23. 23

    ctypes.Structure.from_buffer_copy doesn't check \0 for c_char-type

  24. 24

    Python 3 ctypes call to a function that needs an indirect reference to a buffer through another structure

  25. 25

    How to print contents of ctypes string buffer

  26. 26

    Pass a pickle buffer from Node to Python

  27. 27

    Python, How to get an image from a Buffer/stream

  28. 28

    Buffer.from(<string>, 'hex') equivalent in Python

  29. 29

    Returning a C array from a C function to Python using ctypes

HotTag

Archive