开发者

Creating a structure from bytes with ctypes and IronPython

开发者 https://www.devze.com 2022-12-30 03:31 出处:网络
I have the following CPython code which I now try to run in IronPython: import ctypes class BarHeader(ctypes.Structure):

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
0

精彩评论

暂无评论...
验证码 换一张
取 消