Oren
Oren

Reputation: 94

Trouble reading file into ctypes structure

I have a raw binary file which I'm trying to cast/move into a ctypes structure I've made, but I can't seem to find the right command to do it.

Simplified version of my code:


class Example_Structure(Structure):
    _fields_ = [
        ("a", c_uint16),
        ("b", c_uint16, 14),
        ("c", c_uint16, 2),
        ("d", c_uint16)
    ]

    #reading a file using open() and getting file size

    buf = create_string_buffer(file_size)
    file_object.readinto(buf)
    struct = Example_Structure()      
    memmove(addressof(struct),buf,48) #This is the line I'm unsure about
    # Maybe use cast(buf,struct) ?
    print(struct.a)

I usually get "ArgumentError: argument 1: <type 'exceptions.TypeError'>: wrong type" on the memmove line when trying this without addressof(struct), but using addressof just gives me 0 for every field.

Thanks for your help

EDIT: I've found some success using this:

tmp = cast(addressof(buf),POINTER(struct)).contents

Upvotes: 1

Views: 568

Answers (2)

Mark Tolonen
Mark Tolonen

Reputation: 177715

It's easier than you think. ctypes.Structure supports the buffer protocol, so you can directly do:

buf = Example_Structure()
file_object.readinto(buf)

Example:

from ctypes import *

class Example_Structure(Structure):
    _fields_ = [
        ("a", c_uint16),
        ("b", c_uint16, 14),
        ("c", c_uint16, 2),
        ("d", c_uint16)
    ]

# Create some raw test data
with open('test.bin','wb') as f:
    f.write(b'\x22\x33\xff\x7f\xaa\x55')

buf = Example_Structure()

with open('test.bin','rb') as file_object:
    file_object.readinto(buf) # Will read sizeof(buf) bytes from file

print(f'{buf.a:04x} {buf.b:04x} {buf.c:04x} {buf.d:04x}')

Output:

3322 3fff 0001 55aa

Upvotes: 0

bfris
bfris

Reputation: 5805

I think the size of your Structure should be 64. But you don't even have to guess. Use sizeof so your memmove statement becomes

memmove(addressof(struct),buf,sizeof(struct)) 

The nice feature of this is that if you make a change to the fields in Example_Structure, you don't have to go back and compute the size.

Finally, I'd recommend you rename your variable from struct to something else. If you ever decide to use the popular struct module that is built into the standard library, you could get into trouble with naming collisions.

Upvotes: 1

Related Questions