Creating a structure from bytes with ctypes and IronPython
I have the following CPython code which I now try to run in 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)
The last line raises this exception: TypeError: expected array, got str
I tried BarHeader.from_buffer_copy(bytes(header_raw))
instead o开发者_如何学Cf the above, but then the exception message changes to TypeError: expected array, got bytes
.
Any idea what I'm doing wrong?
I tried the following code in Python 2.7 and it worked perfectly.
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
And a solution using the array class
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
You can use the struct module instead of ctypes for working with packed binary data.
It uses a format string, with characters defining the type of data to pack/unpack.
The documentation is found here. The format string to read an array of four chars, then a unsigned integer would be '4sI'.
's' is the character for char array, while 4 specifies length. 'I' is the character for unsigned int.
Example code:
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)
Although this is an old post, I was able to get this to work with IP version 2.7.5 using the Python 2.7 library.
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
精彩评论