I have the following C struct:
typedef struct {
uint8_t a;
uint8_t b;
uint32_t c;
uint8_t* d;
}
With ctypes, via a callback
You are assuming that c
directly follows b
which is not the case. The compiler will pad a few bytes, 2 on x86, in that structure to align c
.
The proper way is to declare one-to-one mapping of your structure in ctypes
:
from ctypes import *
class object_t(Structure):
_fields_ = [
('a', c_uint8),
('b', c_uint8),
('c', c_uint32),
('d', POINTER(c_uint8)),
]
No you can obtain the value of any member thought this type.
C example library:
#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);
}
Using it from 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))