Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
访问递归Python ctypes结构时出现分段错误_Python_Ctypes - Fatal编程技术网

访问递归Python ctypes结构时出现分段错误

访问递归Python ctypes结构时出现分段错误,python,ctypes,Python,Ctypes,我在使用Python CType访问嵌入到其他结构中的结构中的元素时遇到问题 以下是C: struct GSList { void* data; GSList* next; }; struct att_range { uint16_t start; uint16_t end; }; struct gatt_primary { char uuid[38]; int changed; struct att_range* range; };

我在使用Python CType访问嵌入到其他结构中的结构中的元素时遇到问题

以下是C:

struct GSList
{
    void* data;
    GSList* next;
};

struct att_range
{
    uint16_t start;
    uint16_t end;
};

struct gatt_primary
{
    char uuid[38];
    int changed;
    struct att_range* range;
};

typedef void( *python_callback_t )( GSList* services );

static python_callback_t pycb = NULL;

// pycb is set to a valid function pointer before the callback below is called.

static void primary_all_cb( GSList *services, uint8_t status )
{
    if( status == 0 ) {
        pycb( services );
    }
}
下面是Python:

import ctypes

# CDLL is used to access a shared library that contains the C code above

class range(ctypes.Structure):
    _fields_ = [
        ('starthnd', ctypes.c_uint16),
        ('endhnd', ctypes.c_uint16)
    ]

class service(ctypes.Structure):
    _fields_ = [
        ('uuid', ctypes.c_char_p),
        ('changed', ctypes.c_int),
        ('range', ctypes.POINTER(range))
    ]

class servicelist(ctypes.Structure):
    pass
servicelist._fields_ = [
    ('data', ctypes.POINTER(service)),
    ('next', ctypes.POINTER(servicelist))
]

CB_FUNC_TYPE = ctypes.CFUNCTYPE(None, ctypes.POINTER(servicelist))
def cb(csvclist):
    svclist = ctypes.cast(csvclist, ctypes.POINTER(servicelist))
    data = ctypes.cast(svclist.contents.data, ctypes.POINTER(service))
    next = ctypes.cast(svclist.contents.next, ctypes.POINTER(servicelist))
    hndrange = ctypes.cast(data.contents.range, ctypes.POINTER(range))
    starthnd = ctypes.cast(hndrange.contents.starthnd, ctypes.c_uint16)
    endhnd = ctypes.cast(hndrange.contents.endhnd.contents,  ctypes.c_uint16)
    uuid = ctypes.cast(data.contents.uuid, ctypes.c_char_p)
    print('start: 0x%X, end: 0x%X, uuid: %s' % (starthnd, endhnd, uuid))
cb_func = CB_FUNC_TYPE(cb)

// gatt is the shared library. ble_start source is not shown here, but it sets the callback function pointer.
gatt.ble_start(cb_func)
我使用的是Python3.4和GCC4.7。这不包括最初调用以触发回调函数的函数或访问共享库的Python代码。我已经验证了所有信息都填充了C中的结构,并且能够在某一时刻用Python打印uuid的内容。当我试图访问hndrange时,我遇到了一个分段错误。我可以在Python中打印hndrange的对象引用,但是如果我试图访问元素,就会出现分段错误

我做错了什么


非常感谢您的帮助。

您的
服务
类与
gatt\u主要结构不匹配
uuid
应该是
char
的数组,而不是指针:

class service(ctypes.Structure):
    _fields_ = [
        ('uuid', ctypes.c_char*38),
        ('changed', ctypes.c_int),
        ('range', ctypes.POINTER(range))
    ]
此外,对结构的返回字段使用强制转换也不是一个好主意。查看文档后,您会发现,对于这些类型,将返回相关的python类型。所有其他派生类型都按原样返回


因此,例如
ctypes.cast(hndrange.contents.starthnd,ctypes.c_uint16)
将尝试将python
int
类型转换为
ctypes.c_uint16

谢谢。我这样做了,但我还是有seg故障。当我试图从range访问其中一个结构元素时,即在以下行出现此错误:
starthnd=ctypes.cast(hndrange.contents.starthnd,ctypes.c_uint16)
我可以看到该元素的地址与c代码中的地址匹配。显然,取消对它的引用会导致seg错误。我添加了一些关于您正在进行的转换的信息。我希望这会有帮助。我相信我知道发生了什么,但如果我错了,请纠正我。我一直在尝试从另一个进程访问内存。在Linux(最有可能是OSs)中,进程之间的共享内存通常是不允许的(这是有充分理由的)。因此,我相信实际上是操作系统发出了seg错误,与Python或C实现无关(除了尝试在进程之间共享内存)。@JohnasCukier,前4个
cast
操作是不必要的。接下来的两个(
starthnd
endhnd
)不仅是不必要的,而且是错误的,因为您只能强制转换为指针类型。
uuid
的最后一次转换是不必要的,并且是由于错误地使用了
char*
指针(4或8字节)而不是使用38字节
char
数组。如果按照建议使用
c_char*38
数组类型,您会发现访问
c_char
数组字段会返回一个Python字符串。这里不需要强制转换任何内容。@JohnasCukier,对一个常见的内置函数(如
range
)的名称进行阴影处理也是个坏主意。