How to access data from pointer in struct from Python with ctypes?

后端 未结 1 1632
情话喂你
情话喂你 2021-01-03 11:35

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

1条回答
  •  别那么骄傲
    2021-01-03 11:55

    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))
    

    0 讨论(0)
提交回复
热议问题