0

I am trying to convert a c_byte array into different datatypes in Python, e.g. converting a eight-entry c_byte array into a int64 or double.

In my project, I read a long c_byte array (n>500) containing multiple sensor values with different datatypes. So maybe the first entry is a bool, the second and third entry represent a int8 and entries 4-11 store a double. I am looking for a convenient way of casting those array-entries into the required datatypes.

At the moment, I am transcribing the byte-array into strings containing the binary number. I was thinking about manually writing functions to convert those strings into floats and ints, but I hope there is a more elegant way of doing so. Also, i run into problems converting signed ints...

def convert_byte_to_binary(array):
    binary = ''
    for i in array:
        binary += format(i, '#010b')[2:]

    return binary

def convert_binary_to_uint(binary):
    return int(binary, 2)


array = read_cbyte_array(address, length)  # reads an array of size length, starting at address
array
[15, 30, 110, 7, 65]

convert_byte_to_binary(array)
'0000111100011110011011100000011101000001'

I found the bitstring library, which does something very similar to what I want. Unfortunately, I did not find any support for 64bit integers or double floats.

Ideally, I would have a set of function that can convert the ctypes.c_byte-array into the corresponding ctypes-types.

Nico
  • 49
  • 5
  • https://docs.python.org/3/library/struct.html is exactly what you need. As an example: https://stackoverflow.com/questions/37990060/python-struct-pack-behavior/38003729#38003729. – CristiFati May 03 '19 at 08:28

1 Answers1

0

The struct library is intended for this.

Here's a short example. The value '<?2b8d' represents:

  • < little-endian
  • ? bool
  • 2b two 1-byte signed int.
  • 8d eight doubles.

import ctypes
import struct

# Build the raw data
org_data = struct.pack('<?2b8d',True,-1,2,1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8)
print(org_data)

# Just to demo using a c_byte array...
byte_data = (ctypes.c_byte * len(org_data))(*org_data)
print(byte_data)

# convert to the original data
data = struct.unpack('<?2b8d',byte_data)
print(data)

Output:

b'\x01\xff\x02\x9a\x99\x99\x99\x99\x99\xf1?\x9a\x99\x99\x99\x99\x99\x01@ffffff\n@\x9a\x99\x99\x99\x99\x99\x11@\x00\x00\x00\x00\x00\x00\x16@ffffff\x1a@\xcd\xcc\xcc\xcc\xcc\xcc\x1e@\x9a\x99\x99\x99\x99\x99!@'
<__main__.c_byte_Array_67 object at 0x0000025D4066B0C8>
(True, -1, 2, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8)
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251