¿Cómo acceder a los datos desde el puntero en la estructura de Python con ctypes?

Tengo la siguiente estructura de C:

typedef struct { uint8_t a; uint8_t b; uint32_t c; uint8_t* d; } 

Con ctypes, a través de una callback, puedo obtener un puntero a dicha estructura en Python, llamémoslo ref . Puedo obtener fácilmente a, b, c de esta manera:

 from ctypes import cast, c_uint8, c_uint32, POINTER a = cast(ref, POINTER(c_uint8)).contents.value b = cast(ref + 1, POINTER(c_uint8)).contents.value c = cast(ref + 2, POINTER(c_uint32)).contents.value 

pero no puedo leer los bytes de d. Intenté lo siguiente:

 d_pointer = cast(ref + 6, POINTER(POINTER(c_uint8))).contents first_byte_of_d = d_pointer.contents print type(first_byte_of_d) # prints  print first_byte_of_d 

En esta última línea encuentro un SIGSEGV al depurar con gdb. Entonces, la pregunta es, ¿cómo debería uno acceder al primer byte de un puntero desde una estructura en Python?

Está asumiendo que c sigue directamente a b que no es el caso. El comstackdor rellenará algunos bytes, 2 en x86, en esa estructura para alinear c .

La forma adecuada es declarar la asignación uno a uno de su estructura en ctypes :

 from ctypes import * class object_t(Structure): _fields_ = [ ('a', c_uint8), ('b', c_uint8), ('c', c_uint32), ('d', POINTER(c_uint8)), ] 

No se puede obtener el valor de cualquier miembro pensado en este tipo.

Biblioteca de ejemplos en C:

 #include  #include  struct object_t { uint8_t a; uint8_t b; uint32_t c; uint8_t* d; }; static struct object_t object = {'a', 'b', 12345, NULL}; struct object_t * func1(void) { return &object; } void func2(void(*callback)(struct object_t *)) { callback(&object); } 

Usándolo desde Python:

 from ctypes import * class object_t(Structure): _fields_ = [ ('a', c_uint8), ('b', c_uint8), ('c', c_uint32), ('d', POINTER(c_uint8)), ] callback_t = CFUNCTYPE(None, POINTER(object_t)) lib = CDLL('./file.dll') func1 = lib.func1 func1.argtypes = None func1.restype = POINTER(object_t) func2 = lib.func2 func2.argtypes = [callback_t] func2.restype = None ret = func1() a = ret.contents.a b = ret.contents.b c = ret.contents.c d = ret.contents.d def mycallback(obj): a = obj.contents.a b = obj.contents.b c = obj.contents.c d = obj.contents.d func2(callback_t(mycallback))