Segfault在从Win32移植到Linux

时间:2017-05-18 20:46:09

标签: python linux ctypes

我有从Windows移植的库,我使用ctypes从Python调用。这个组合在32位和64位Windows上运行,使用python 2.7和3.5,但在移植到我当前的Linux环境后使用段错误,使用gcc 6.3和python 3.5运行Ubuntu 17.04。

该库有两个回调,签名略有不同。第一个按预期运行,但是在ctypes库中第二个段错误。

C中的回调签名是:

typedef void (*StatusCallback)(void* ctxt, enum STATUS status, void* data);
typedef void (*MsgCallback)(void* ctxt, enum STREAM stream, DataMsg* msg);

并使用ctypes定义为

STATUSCB = CFUNCTYPE(None, c_void_p, c_uint, c_void_p)
MSGCB = CFUNCTYPE(None, c_void_p, c_uint, POINTER(DataMsg))

它是第二个失败的回调,它与它的最后一个参数(即POINTER(DataMsg))中的第一个不同。在C DataMsg中定义为:

typedef struct DataItem
{
    uint8_t* name;
    enum DATATYPE type;
    uint8_t* unit;
    uint32_t numValues;
    void* values;
    enum DATASTATUS* valueStatuses;
    uint32_t numChildren;
    struct DataItem* children;
}
DataItem;

typedef struct DataMsg
{
    uint64_t timestamp;
    uint32_t numItems;
    struct DataItem* items;
}
DataMsg;

在python中:

DataItemPtr = POINTER(DataItem)

DataItem._fields_ = [
    ('name', c_char_p),
    ('type', c_uint),
    ('unit', c_char_p),
    ('numValues', c_uint),
    ('values', c_void_p),
    ('valueStatuses', POINTER(c_uint)),
    ('numChildren', c_uint),
    ('children', DataItemPtr) ]

DataMsg._fields_ = [
    ('timestamp', c_ulonglong),
    ('numItems', c_uint),
    ('items', DataItemPtr) ]

这是在gdb下运行时获得的堆栈跟踪:

Thread 5 "python3" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffec7ba700 (LWP 17002)]
0x00007ffff66b4b8e in ?? ()
   from /usr/lib/python3.5/lib-dynload/_ctypes.cpython-35m-x86_64-linux-gnu.so
(gdb) bt
#0  0x00007ffff66b4b8e in ?? ()
   from /usr/lib/python3.5/lib-dynload/_ctypes.cpython-35m-x86_64-linux-gnu.so
#1  0x00007ffff66b4f4c in ?? ()
   from /usr/lib/python3.5/lib-dynload/_ctypes.cpython-35m-x86_64-linux-gnu.so
#2  0x00007ffff66b57b7 in ffi_closure_unix64_inner ()
   from /usr/lib/python3.5/lib-dynload/_ctypes.cpython-35m-x86_64-linux-gnu.so
#3  0x00007ffff66b5c10 in ffi_closure_unix64 ()
   from /usr/lib/python3.5/lib-dynload/_ctypes.cpython-35m-x86_64-linux-gnu.so
#4  0x00007fffe801972c in HandleSysDescriptor (Channel=0x7fffe000f3a0, 
    channel=0x7fffe000f570, flow_id=2, dict=0x7fffe0024368, msg=0x7fffe0020470)
    at /home/michael/dev//linux/source/ARCDevKit/SapphireReceive.c:471
#5  0x00007fffe8018fb2 in HandleMessage (channel=0x7fffe000f570, flow_id=2, 
    dict=0x7fffe0024368, msg=0x7fffe0020470)
    at /home/michael/dev//linux/source/ARCDevKit/SapphireReceive.c:290
#6  0x00007fffe8024860 in process_item (channel=0x7fffe000f570, flow_id=2, 
    dict=0x7fffe0024368, mesg=0x7fffe0020470)
    at /home/michael/dev//linux/source/SbxCLib/sbxc/usnet/us_tcp_channel_connection.c:97

我尝试用c_void_p替换POINTER(DataMsg)以查看是否可以获得回调以输入python代码,但是发生了同样的错误。我担心枚举的大小与用于枚举参数类型的c_uint有关,但它适用于第一次回调,而不是第二次回调。

直接从C调用它是有效的,这是怀疑我使用ctypes的另一个原因。

它也可以在Windows下使用许多不同的VS版本(2005年,2008年,2013年,2015年)进行多种不同的排列,因此我怀疑在处理指针,枚举或整数方面存在某种差异,但我还没有找到任何特定的东西。

0 个答案:

没有答案