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

0 投票
3 回答
7739 浏览
提问于 2025-04-15 22:30

我有一段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 个回答

0

虽然这是一篇旧帖子,但我成功地在使用Python 2.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
1

你可以使用struct模块来处理打包的二进制数据,而不是使用ctypes。

这个模块使用一种格式字符串,里面的字符用来定义要打包或解包的数据类型。

你可以在这里找到相关文档。要读取一个包含四个字符的数组,接着是一个无符号整数,格式字符串是'4sI'。

's'表示字符数组,而4则指定了长度。'I'表示无符号整数。

示例代码:

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

我在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

撰写回答