说我在C
中有以下代码union u_type
{
uint32_t data;
uint8_t chunk[4];
} 32bitsdata;
32bitsdata.chunk[0] = some number;
32bitsdata.chunk[1] = some number;
32bitsdata.chunk[2] = some number;
32bitsdata.chunk[3] = some number;
printf("Data in 32 bits: %d\n", 32bitsdata.data);
我怎么能在python中做类似的事情?
我试图读取二进制文件(逐字节) - 已经使它工作,并将每3个字节组合成一个int。听说结构会起作用,但我不确定如何。
最佳,
亨利
答案 0 :(得分:7)
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 use 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)
答案 1 :(得分:1)
这是你要做的。首先,让我们创建我们需要的原始字节,我将作弊并使用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'
这些可以很容易地从文件中读取。现在,使用struct
模块是微不足道的。我们使用unsigned int格式字符'I'
:
>>> import struct
>>> list(struct.iter_unpack('I', raw_bytes))
[(8,), (4,), (2,), (4,), (8,)]
注意,每次迭代我们都会返回一个元组,因为我们的struct有一个成员,它是一个单元组的列表。但是进入一个平坦的python列表是微不足道的:
>>> [t[0] for t in struct.iter_unpack('I', raw_bytes)]
[8, 4, 2, 4, 8]
另一种选择是将它们读入array.array
:
>>> import array
>>> my_array = array.array('I', raw_bytes)
>>> my_array
array('I', [8, 4, 2, 4, 8])
答案 2 :(得分:0)
您询问了C联合,但是如果您的目标是将3个字节分组为一个int,则可以改用Python struct.unpack。
import struct
chunk = bytearray()
chunk.append(0x00) # some number
chunk.append(0xc0) # some number
chunk.append(0xff) # some number
chunk.append(0xee) # some number
# Convert to a 32-bit unsigned int.
# You didn't specify the byte-order, so I'm using big-endian.
# If you want little-endian instead, replace the '>' symbol by '<'.
data = struct.unpack('>I', chunk)[0] # unpack returns a tupple, but we only need the first value
print(hex(data)) # the terminal prints 0xc0ffee
答案 3 :(得分:0)
如果您要进行数值运算,您可能还是想使用numpy库,因此请考虑numpy的ndarray类型的“ view”方法。原始ndarray可以通过view-array进行查看和修改。
>>> import numpy as np
>>> a = np.uint32([1234567890])
>>> b = a.view(np.uint8)
>>> print(a)
[1234567890]
>>> print(b)
[210 2 150 73]
>>> b[2] = 10
>>> print(*b)
210 2 10 73
>>> print(*a)
1225392850