Python ctypes到np.dtype转换位域

时间:2017-10-25 09:15:18

标签: python numpy ctypes

我正在接收来自我尝试解码的服务器的字节串。我设法找出了ctypes结构(参见代码),但它包含位字段。

我通常只使用np.frombuffer函数来获取数据,因为它识别大多数ctypes。此外,我可以将数据写入HDF5文件,而无需进行任何操作。然而,由于位域,dtype大小和ctype大小不匹配并且数据被转换,但是完全错误。您应该可以按原样运行下面的代码。

import ctypes
import numpy as np

#%%
class SubStruct(ctypes.Structure):
    _pack_ = 1
    _fields_ = [('bUnderrange', ctypes.c_ubyte, 1),
                ('bOverrange', ctypes.c_ubyte, 1),
                ('bLimit_1a', ctypes.c_ubyte, 1),
                ('bLimit_1b', ctypes.c_ubyte, 1),
                ('bLimit_2a', ctypes.c_ubyte, 1),
                ('bLimit_2b', ctypes.c_ubyte, 1),
                ('bError', ctypes.c_ubyte, 1),
                ('TXPDO', ctypes.c_ubyte)] #This is a byte, rest are bits

class MainStruct(ctypes.Structure):
    _pack_ = 4
    _fields_ = [('stStatus', SubStruct),
                ('nValue', ctypes.c_ushort),
                ('fValue', ctypes.c_float)]

rawdata = b'X\x00W\x00ff\x86AV\x00\xd6\x0033{B\n\x00-\x00ff\x9aAW\x00\xc8\x01ff\nB'

#%%
a = SubStruct()
b = MainStruct()

print('Data size: ',len(rawdata))
print('\nSubStruct:')
print('Ctype size: ',ctypes.sizeof(a))
print('Dtype size: ',np.dtype(a).itemsize)
print('\nMainStruct:')
print('Ctype size: ',ctypes.sizeof(b))
print('Dtype size: ',np.dtype(b).itemsize)

data = np.frombuffer(rawdata, dtype=MainStruct) #WRONG

我期望以下内容:

array([((0, 0, 0, 1, 1, 0, 1), 87, 16.8),
       ((0, 1, 1, 0, 1, 0, 1), 214, 62.8),
       ((0, 1, 0, 1, 0, 0, 0), 45, 19.3),
       ((1, 1, 1, 0, 1, 0, 1), 456, 34.6)])

我得到的是:

array([((88, 0, 87, 0, 102, 102, 134, 65), 86,  62.79999924),
       ((10, 0, 45, 0, 102, 102, 154, 65), 87,  34.59999847)])

当ctype可用时,是否有一种有效的方法来获得正确的dtype?还是一种有效地操作rawdata的方法,这样我仍然可以应用np.frombuffer函数?

1 个答案:

答案 0 :(得分:1)

从numpy 1.16(#12254)开始,这将返回错误,而不是产生错误的结果:

>>> data = np.frombuffer(rawdata, dtype=MainStruct)
TypeError: ctypes bitfields have no dtype equivalent

NumPy不支持位域,因此无法实现此目的。最好的选择是定义一个不包含位域的替换类型,并改用它。

如果您以后看到这样的不正确行为,强烈建议您在NumPy问题跟踪器中报告该行为,尤其是考虑到您的例子很少。