如何使用ctypes从Python的struct中的指针访问数据? [英] How to access data from pointer in struct from Python with ctypes?

查看:714
本文介绍了如何使用ctypes从Python的struct中的指针访问数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下C结构:

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

使用ctypes,通过回调,我能够在Python中获得指向此类结构的指针,我们将其称为ref.我可以通过这种方式轻松获得a,b,c:

With ctypes, via a callback, I am able to obtain a pointer to such a struct in Python, let's call it ref. I can easily obtain a, b, c this way:

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

但是我无法从d读取字节.我尝试了以下方法:

but I can't read the bytes from d. I tried the following:

d_pointer = cast(ref + 6, POINTER(POINTER(c_uint8))).contents
first_byte_of_d = d_pointer.contents
print type(first_byte_of_d) # prints <class 'ctypes.c_ubyte'>
print first_byte_of_d

在最后一行中,使用gdb调试时遇到了SIGSEGV.所以问题是,如何从Python中的结构访问指针的第一个字节?

At this last line I encounter a SIGSEGV when debugging with gdb. So the question is, how should one access the first byte of a pointer from a struct in Python?

推荐答案

您假定c直接跟在b之后,情况并非如此.编译器将在该结构中填充x86上的几个字节,以对齐c.

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.

正确的方法是在ctypes中声明结构的一对一映射:

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示例库:

#include <stdint.h>
#include <stdlib.h>

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

从Python使用它:

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

这篇关于如何使用ctypes从Python的struct中的指针访问数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆