Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python ctypes structure wrong byte size

Tags:

python

ctypes

So I'm trying to figure out why the size of my ctypes.Structure is not what it should be. My code is the following, theres also the calculation of what the size should be afaik.

class FILE_HEAD(ctypes.Structure):
    _fields_ = [
        ("name", ctypes.c_char * 4),                    # 4 bytes
        ("size", ctypes.c_int),                         # 4 bytes
        ("Cal_l", ctypes.c_double),                     # 8 bytes
        ("Cal_r", ctypes.c_double),                     # 8 bytes
        ("Speed_ChL", ctypes.c_byte),                   # 1 byte
        ("Speed_Pulses_ChL", ctypes.c_int),             # 4 bytes
        ("Speed_factor_ChL", ctypes.c_double),          # 8 bytes
        ("Quantity_ChL", ctypes.c_char * 3),            # 3 bytes
        ("Description_ChL", ctypes.c_char * 32),        # 32 bytes
        ("Unit_ChL", ctypes.c_char * 8),                # 8 bytes
        ("Speed_ChR", ctypes.c_byte),                   # 1 byte
        ("Speed_Pulses_ChR", ctypes.c_int),             # 4 bytes
        ("Speed_factor_ChR", ctypes.c_double),          # 8 bytes
        ("Quantity_ChR", ctypes.c_char * 3),            # 3 bytes
        ("Description_ChR", ctypes.c_char * 32),        # 32 bytes
        ("Unit_ChR", ctypes.c_char * 8)                 # 8 bytes
    ]                                                   # = 136 bytes

So I think that Structure should have a size of 136 bytes. But when I let python print the size of an instance of the structure print ctypes.sizeof(COMI_HEAD) I get 144. I do not know where those 8 bytes come from.

I've filled that with the following data and wrote that to a file to see all the bytes and analyze where the bytes are.

comi = FILE_HEAD()
comi.name = "COMI"
comi.size = ctypes.sizeof(comi) - 8
comi.Cal_l = 342.324
comi.Cal_r = 342.324
comi.Speed_ChL = ctypes.c_byte(1)
comi.Speed_Pulses_ChL = 123
comi.Speed_factor_ChL = 123.456
comi.Quantity_ChL = "Tes"
comi.Description_ChL = "Test Desc"
comi.Unit_ChL = "t/t"
comi.Speed_ChR = ctypes.c_byte(1)
comi.Speed_Pulses_ChR = 123
comi.Speed_factor_ChR = 123.456
comi.Quantity_ChR = "Tes"
comi.Description_ChR = "Test Desc"
comi.Unit_ChR = "t/t"

Here is what my HEX-Viewer shows me. I've marked red, which bytes I think are the 8 bytes that are too much, but I do not know where these 8 bytes come from. The first 3 bytes I marked come directly after the Speed_ChL which should be 1 byte but looks like its 4 bytes. The next 5 bytes I've marked are at the end of the file. Theres this string Unit_ChR which should be 8 bytes but looks like it is 13 bytes.

enter image description here

Can someone tell me where my mistake is? What am I doing wrong here? Any help is appreciated!

like image 327
patsimm Avatar asked Dec 17 '14 08:12

patsimm


People also ask

What is ctypes CDLL?

ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

How do I use ctypes in Python?

When using the functions, ctypes will check if the arguments fit to these types. The type expects each array element as an argument, so we use the asterisk notation with numbers. The result has the type ctypes. c_int and we want to return a python integer, therefore int(result) is returned.

What is C_char_p?

c_char_p is a subclass of _SimpleCData , with _type_ == 'z' . The __init__ method calls the type's setfunc , which for simple type 'z' is z_set . In Python 2, the z_set function (2.7.

What is C_ubyte?

The cubit, generally taken as equal to 18 inches (457 mm), was based on the length of the arm from the elbow to the tip of the middle finger and was considered the equivalent of 6 palms or 2 spans.


1 Answers

Ok so I've found the solution. Thanks to Andreas who told me that my problem has to do with the offset. So the solution is to add a _pack_ = 1 to the structure like that.

class FILE_HEAD(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("name", ctypes.c_char * 4),                    # 4 bytes
        ("size", ctypes.c_int),                         # 4 bytes
        ("Cal_l", ctypes.c_double),                     # 8 bytes
        ("Cal_r", ctypes.c_double),                     # 8 bytes
        ("Speed_ChL", ctypes.c_byte),                   # 1 byte
        ("Speed_Pulses_ChL", ctypes.c_int),             # 4 bytes
        ("Speed_factor_ChL", ctypes.c_double),          # 8 bytes
        ("Quantity_ChL", ctypes.c_char * 3),            # 3 bytes
        ("Description_ChL", ctypes.c_char * 32),        # 32 bytes
        ("Unit_ChL", ctypes.c_char * 8),                # 8 bytes
        ("Speed_ChR", ctypes.c_byte),                   # 1 byte
        ("Speed_Pulses_ChR", ctypes.c_int),             # 4 bytes
        ("Speed_factor_ChR", ctypes.c_double),          # 8 bytes
        ("Quantity_ChR", ctypes.c_char * 3),            # 3 bytes
        ("Description_ChR", ctypes.c_char * 32),        # 32 bytes
        ("Unit_ChR", ctypes.c_char * 8)                 # 8 bytes
    ]                                                   # = 136 bytes
like image 164
patsimm Avatar answered Nov 03 '22 01:11

patsimm