Take a look at the ctypes tutorial. You use the ctypes.Union class:
class test(ctypes.Structure):
# ...
class test2(ctypes.Structure):
# ...
class tests(ctypes.Union):
_fields_ = [("a", test),
("b", test2)]
Answer from Adam Rosenfield on Stack OverflowTake a look at the ctypes tutorial. You use the ctypes.Union class:
class test(ctypes.Structure):
# ...
class test2(ctypes.Structure):
# ...
class tests(ctypes.Union):
_fields_ = [("a", test),
("b", test2)]
Simply create a class that inherits from ctypes.Union.
Read more about it here.
You then define the union fields in the _fields_ class member.
python - Confusion in implementing union using ctypes - Stack Overflow
python - Python3: ImportError: No module named '_ctypes' when using Value from module multiprocessing - Stack Overflow
Equivalent of a C union in Python? - Stack Overflow
Python ctype Structure/Union Issue - Stack Overflow
Installing libffi-dev and re-installing python3.7 fixed the problem for me.
to cleanly build py 3.7 libffi-dev is required or else later stuff will fail
If using RHEL/Fedora:
sudo yum install libffi-devel
or
sudo dnf install libffi-devel
If using Debian/Ubuntu:
sudo apt-get install libffi-dev
If you use pyenv and get error "No module named '_ctypes'" (like i am) on Debian/Raspbian/Ubuntu you need to run this commands:
sudo apt-get install libffi-dev
pyenv uninstall 3.7.6
pyenv install 3.7.6
Put your version of python instead of 3.7.6
What about ctypes?
from ctypes import (
Union, Array,
c_uint8, c_uint32,
cdll, CDLL
)
class uint8_array(Array):
_type_ = c_uint8
_length_ = 4
class u_type(Union):
_fields_ = ("data", c_uint32), ("chunk", uint8_array)
# load printf function from Dynamic Linked Libary libc.so.6 (I'm using linux)
libc = CDLL(cdll.LoadLibrary('libc.so.6')._name)
printf = libc.printf
if __name__ == "__main__":
# initialize union
_32bitsdata = u_type()
# set values to chunk
_32bitsdata.chunk[:] = (1, 2, 3, 4)
# and print it
printf(b"Data in 32 bits: %d\n", _32bitsdata.data)
Here is what you would do. First, let's create the raw bytes we need, I'll cheat and use numpy:
>>> import numpy as np
>>> arr = np.array((8,4,2,4,8), dtype=np.uint32)
>>> arr
array([8, 4, 2, 4, 8], dtype=uint32)
>>> raw_bytes = arr.tobytes()
>>> raw_bytes
b'\x08\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x08\x00\x00\x00'
These could have easily been read from a file. Now, using the struct module is trivial. We use the unsigned int format character 'I':
>>> import struct
>>> list(struct.iter_unpack('I', raw_bytes))
[(8,), (4,), (2,), (4,), (8,)]
Note, each time we iterate we get back a tuple, since our struct has one member, it is a list of singleton tuples. But this is trivial to get into a flat python list:
>>> [t[0] for t in struct.iter_unpack('I', raw_bytes)]
[8, 4, 2, 4, 8]
Another alternative is to read them into an array.array:
>>> import array
>>> my_array = array.array('I', raw_bytes)
>>> my_array
array('I', [8, 4, 2, 4, 8])