Curious segfault when using Python CTypes union with 4 structs but not less

时光总嘲笑我的痴心妄想 提交于 2019-12-11 13:08:37

问题


I'm running into a curious segfault when trying to interface to a library using Python CTypes. I'm running Python 3.4.0-0ubuntu2 on Kubuntu Trusty 64 bit.

The segfault occurs when I use 4 anonymous structs within a union but not when I use 3 or less, which is most curious. It also occurs only when I try to return a union back to Python in fn2 but not when I just send it from Python in fn1.

The code with 3 structs which does not segfault:

lib.c:

#include <stdio.h>

typedef union {
    int data[3];
    struct { int r, g, b; };
    struct { int x, y, z; };
    struct { int l, a, B; }; // cap B to silence error
} Triplet;

void fn1(Triplet t)
{
    fprintf(stderr, "%d, %d, %d\n", t.r, t.g, t.b);
}

Triplet fn2(Triplet t)
{
    Triplet temp = {{t.r + 1, t.g + 1, t.b + 1}};
    return temp;
}

main.py:

from ctypes import *

def _makeFields(s):
    return tuple([(c, c_int) for c in s])

Array3 = c_int * 3

class _RGB(Structure): _fields_ = _makeFields("rgb")
class _XYZ(Structure): _fields_ = _makeFields("xyz")
class _LAB(Structure): _fields_ = _makeFields("laB") # cap B to silence error

class Triplet(Union):
    _anonymous_ = ["rgb", "xyz", "laB"]
    _fields_ = [("data", Array3),
                ("rgb", _RGB),
                ("xyz", _XYZ),
                ("laB", _LAB)]

_lib = CDLL("libuniontest.so")
_lib.fn1.argtypes = [Triplet]
_lib.fn2.restype = Triplet
_lib.fn2.argtypes = [Triplet]

t = Triplet(Array3(99, 129, 39))
_lib.fn1(t)
tt = _lib.fn2(t)
print(tuple(tt.data))

Makefile:

test:
    $(CC) -fPIC -shared -o libuniontest.so lib.c
    sudo cp libuniontest.so /usr/local/lib/
    sudo ldconfig
    python3 main.py

Decreasing the number of struct members also is not a problem. (Totally removing the struct members leads to another problem, though.) Now to demonstrate the segfault just add one more anonymous struct:

in lib.c:

typedef union {
    int data[3];
    struct { int r, g, b; };
    struct { int x, y, z; };
    struct { int l, a, B; }; // cap B to silence error
    struct { int L, c, h; }; // cap L to silence error
} Triplet;

in main.py:

class _RGB(Structure): _fields_ = _makeFields("rgb")
class _XYZ(Structure): _fields_ = _makeFields("xyz")
class _LAB(Structure): _fields_ = _makeFields("laB") # cap B to silence error
class _LCH(Structure): _fields_ = _makeFields("Lch") # cap L to silence error

class Triplet(Union):
    _anonymous_ = ["rgb", "xyz", "laB", "Lch"]
    _fields_ = [("data", Array3),
                ("rgb", _RGB),
                ("xyz", _XYZ),
                ("laB", _LAB),
                ("Lch", _LCH)]

What is the reason for this segfault and how can I fix it? Thanks.

来源:https://stackoverflow.com/questions/33561005/curious-segfault-when-using-python-ctypes-union-with-4-structs-but-not-less

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!