2014-04-17 39 views
1

我已经创建了一个ctype位域结构和相应的联合体,以通过单个位域和整数值来访问它。 我能够使用包含字段名称的变量来设置单个字段,但现在我想知道特定字段属于哪个字节。 这里是我的代码示例:Python ctype-bitfields:获取位域位置

import ctypes 

c_short = ctypes.c_uint16 

class Flags_bits(ctypes.LittleEndianStructure): 
    _fields_ = [ 
     ("bitField1", c_short, 1), 
     ("bitField2", c_short, 4), 
     ("bitField3", c_short, 6), 
     ("bitField4", c_short, 1), 
     ("bitField5", c_short, 2), 
     ("bitField6", c_short, 2), 

     ("bitField7", c_short, 6), 
     ("bitField8", c_short, 4), 
     ("bitField9", c_short, 4), 
     ("bitField10", c_short, 1), 
     ("bitField11", c_short, 1)] 

class Flags(ctypes.Union): 
    _fields_ = [("b", Flags_bits), 
       ("asInt", c_short*6)] 

def setFlag (flagName, value): 
    flags = Flags() 
    setattr(flags.b, flagName, value)   
    print getattr(flags.b, flagName) 

现在我想知道的是哪个整数我旗属于(即其flags.asInt [1]),我一直在寻找一种“ get_location“属性来获取结构中的标志位置,并从中检索整数的”i“索引,但找不到任何东西 有没有简单的方法来做到这一点?

在此先感谢您的回复!

回答

2

Structure中的每个字段描述符都具有offset属性,该属性定义其存储单元的字节偏移量。它还有一个size属性,其含义取决于它是否是位域。如果是位字段,则size的低位字包含字段的存储单元位偏移量,高位字包含该字段中的位数。否则size是字段的大小(以字节为单位)。

由于您的位字段存储单元都c_short,你可以简单地划分sizeof(c_short)字段的字节offset来计算asInt相应的项目。例如,Flags_bits.bitField6.offset // 2 == 0Flags_bits.bitField7.offset // 2 == 1

您也可以计算比特范围内的每个字段:

import ctypes 

c_short = ctypes.c_cshort 

class Flags_bits(ctypes.LittleEndianStructure): 
    _fields_ = [("bitField1", c_short, 1), 
       ("bitField2", c_short, 4), 
       ("bitField3", c_short, 6), 
       ("bitField4", c_short, 1), 
       ("bitField5", c_short, 2), 
       ("bitField6", c_short, 2), 
       ("bitField7", c_short, 6), 
       ("bitField8", c_short, 4), 
       ("bitField9", c_short, 4), 
       ("bitField10", c_short, 1), 
       ("bitField11", c_short, 1)] 


for field_descr in Flags_bits._fields_:   
    name = field_descr[0] 
    field = getattr(Flags_bits, name)  
    bfield_bits = field.size >> 16  
    if bfield_bits: 
     start = 8 * field.offset + field.size & 0xFFFF 
     stop = start + bfield_bits 
    else: 
     start = 8 * field.offset 
     stop = start + 8 * field.size 
    print("{:>10s}: bits {:>2d}:{:>2d}".format(
      name, start, stop)) 

输出:

bitField1: bits 0: 1 
bitField2: bits 1: 5 
bitField3: bits 5:11 
bitField4: bits 11:12 
bitField5: bits 12:14 
bitField6: bits 14:16 
bitField7: bits 16:22 
bitField8: bits 22:26 
bitField9: bits 26:30 
bitField10: bits 30:31 
bitField11: bits 31:32 
+0

谢谢,这有很大帮助!但是在我的机器上(我在Window机器上运行Python 2.7.2),为了不接受投诉,我必须用“_,_”来更改“* _”。但仍然很好的答案。 – toti08

+0

@eryksun:谢谢你的回答!你能告诉我,这个关于位域大小和偏移的东西可以在文档中找到吗?我无法在那里找到它... – maggie

+0

@maggie,文档简要提到了字段描述符类型,但属性没有记录。这只是离开源码,如['PyCField_repr'](https://hg.python.org/cpython/file/648dcafa7e5f/Modules/_ctypes/cfield.c#l271)。 – eryksun