代码之家  ›  专栏  ›  技术社区  ›  Meh

使用ctypes和ironpython从字节创建结构

  •  0
  • Meh  · 技术社区  · 16 年前

    我有下面的cpython代码,我现在尝试在Ironpython中运行:

    import ctypes
    
    class BarHeader(ctypes.Structure):
        _fields_ = [
            ("id", ctypes.c_char * 4),
            ("version", ctypes.c_uint32)]
    
    bar_file = open("data.bar", "rb")
    header_raw = bar_file.read(ctypes.sizeof(BarHeader))
    header = BarHeader.from_buffer_copy(header_raw)
    

    最后一行引发此异常: TypeError: expected array, got str

    我试过 BarHeader.from_buffer_copy(bytes(header_raw)) 而不是上面的,但是异常消息更改为 TypeError: expected array, got bytes .

    知道我做错了什么吗?

    3 回复  |  直到 11 年前
        1
  •  1
  •   evilpie    16 年前

    我在python 2.7中尝试了以下代码,它运行得很好。

    import ctypes  
    
    class BarHeader(ctypes.Structure):
       _fields_ = [("version", ctypes.c_uint)]
    
    
    header = BarHeader.from_buffer_copy("\x01\x00\x00\x00")
    print header.version #prints 1 on little endian
    

    以及使用数组类的解决方案

    import ctypes
    import array
    
    class BarHeader(ctypes.Structure):
       _fields_ = [
          ("id", ctypes.c_char * 4),
          ("version", ctypes.c_uint32)]
    
    bar_file = open("data.bar", "rb")
    
    bytearray = array.array('b')
    bytearray.fromfile(bar_file, ctypes.sizeof(BarHeader))
    
    header = BarHeader.from_buffer_copy(bytearray)
    
    print header.id
    print header.version
    
        2
  •  1
  •   lunixbochs    16 年前

    您可以使用struct模块而不是ctypes来处理压缩的二进制数据。

    它使用一个格式字符串,字符定义要打包/解包的数据类型。

    找到文档 here . 读取四个字符数组的格式字符串,那么无符号整数将是“4si”。

    's'是字符数组的字符,而4指定长度。'I'是无符号int的字符。

    示例代码:

    import struct
    
    header_fmt = struct.Struct("4sI")
    
    bar_file = open("data.bar", "rb")
    header_raw = bar_file.read(header_fmt.size)
    id, version = header_fmt.unpack(header_raw)
    
        3
  •  0
  •   Uncle Meat    11 年前

    尽管这是一篇老文章,但我还是能够让它与使用Python2.7库的IP版本2.7.5一起工作。

    import sys
    sys.path.append(r"C:\Program Files (x86)\IronPython 2.7\Lib")
    
    import ctypes
    import array
    
    class BarHeader(ctypes.Structure):
       _fields_ = [("version", ctypes.c_uint)]
    
    header = BarHeader.from_buffer_copy(array.array('c', ['\x01', '\x00', '\x00', '\x00']))
    print header.version #prints 1 on little endian