python ctypes array of structs

Question:

I have the followng code and it ends up to segmentation fault.

import ctypes
from random import randint

class STRUCT_2(ctypes.Structure):
    #_pack_=2
    _fields_ = [('field_1', ctypes.c_short),
                ('field_2', ctypes.c_short),
                ('field_3', ctypes.c_short)]

class STRUCT_1(ctypes.Structure):
    #_pack_=2
    _fields_ = [('elements', ctypes.c_short),
                ('STRUCT_ARRAY', ctypes.POINTER(STRUCT_2))]

    def __init__(self,num_of_structs):
        elems = (ctypes.POINTER(STRUCT_2) * num_of_structs)()
        self.STRUCT_ARRAY = ctypes.cast(elems,ctypes.POINTER(STRUCT_2))
        self.elements = num_of_structs

        for num in range(0,num_of_structs):
            self.STRUCT_ARRAY[num].field_1 = 1
            self.STRUCT_ARRAY[num].field_2 = 2
            self.STRUCT_ARRAY[num].field_3 = 3

for num in range(0,100):
    test = STRUCT_1(num)
    print "%i done" % num

output:
5 done
Segmentation fault

But if field_3 is not present in struct_2 then it seems to work correctly. If I add one short field (field_4) more it ends to segmentation fault…

So what i’am doing incorrectly or what i have missed here??

Is there someother way to define array size?

Asked By: Juster

||

Answers:

STRUCT_ARRAY in your code should be a pointer to a pointer array, not a pointer to an element in the array, as you are appending STRUCT_2 pointers to the array.

In C, STRUCT_ARRAY can be defined as *STRUCT_2[length], aka an array of STRUCT_2 pointers

import ctypes
from random import randint

class STRUCT_2(ctypes.Structure):
    #_pack_=2
    _fields_ = [('field_1', ctypes.c_short),
                ('field_2', ctypes.c_short),
                ('field_3', ctypes.c_short),
                ('field_4', ctypes.c_short),
                ('field_5', ctypes.c_short),
                ('field_6', ctypes.c_short),
                ('field_7', ctypes.c_short),
                ('field_8', ctypes.c_short)]

class STRUCT_1(ctypes.Structure):
    #_pack_=2
    _fields_ = [('elements', ctypes.c_short),
                #an array of pointers
                ('STRUCT_ARRAY', ctypes.POINTER(ctypes.POINTER(STRUCT_2)))]

    def __init__(self,num_of_structs):
        elems = (ctypes.POINTER(STRUCT_2) * num_of_structs)()
        self.STRUCT_ARRAY = ctypes.cast(elems,ctypes.POINTER(ctypes.POINTER(STRUCT_2)))
        self.elements = num_of_structs

        for num in range(0,num_of_structs):
            self.STRUCT_ARRAY[num].field_1 = 1
            self.STRUCT_ARRAY[num].field_2 = 2
            self.STRUCT_ARRAY[num].field_3 = 3

for num in range(0,100):
    test = STRUCT_1(num)
    print("%i done" % num)

If instead what you want is an array of structs, use the following code:

import ctypes
from random import randint

class STRUCT_2(ctypes.Structure):
    #_pack_=2
    _fields_ = [('field_1', ctypes.c_short),
                ('field_2', ctypes.c_short),
                ('field_3', ctypes.c_short),
                ('field_4', ctypes.c_short),
                ('field_5', ctypes.c_short),
                ('field_6', ctypes.c_short),
                ('field_7', ctypes.c_short),
                ('field_8', ctypes.c_short)]

class STRUCT_1(ctypes.Structure):
    #_pack_=2
    _fields_ = [('elements', ctypes.c_short),
                #an array of structs
                ('STRUCT_ARRAY', ctypes.POINTER(STRUCT_2))]

    def __init__(self,num_of_structs):
        elems = (STRUCT_2 * num_of_structs)()
        self.STRUCT_ARRAY = ctypes.cast(elems,ctypes.POINTER(STRUCT_2))
        self.elements = num_of_structs

        for num in range(0,num_of_structs):
            self.STRUCT_ARRAY[num].field_1 = 1
            self.STRUCT_ARRAY[num].field_2 = 2
            self.STRUCT_ARRAY[num].field_3 = 3
            self.STRUCT_ARRAY[num].field_4 = 4

for num in range(0,100):
    test = STRUCT_1(num)
    print("%i done" % num)
Answered By: simonzack
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.