Abort when passing Python CTypes struct containing array of 3 ints

為{幸葍}努か 提交于 2019-12-08 06:08:59

问题


I'm running Python 3.4.0-0ubuntu2 on Kubuntu Trusty 64 bit.

When trying to find a minimal example for my other related (but not duplicate) question, I found that the following apparently trivial code using Python CTypes causes a SIGABRT upon the call to fn1. (Note that in the other case, fn1 worked fine and it was only fn2 which didn't work and the signal was SIGSEGV there.)

lib.c:

#include <stdio.h>

typedef struct {
    int data[3];
} Triplet;

void fn1(Triplet t)
{
    fprintf(stderr, "%d, %d, %d\n", t.data[0], t.data[1], t.data[2]);
}

Triplet fn2(Triplet t)
{
    Triplet temp = {{t.data[0] + 1, t.data[1] + 1, t.data[2] + 1}};
    return temp;
}

main.py:

from ctypes import *

Array3 = c_int * 3

class Triplet(Union):
    _fields_ = [("data", Array3)]

_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) # this causes segfault
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

It didn't make a difference if I changed Union to Structure.

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


回答1:


This seems to be a bug in libffi (which is what ctypes uses) that only occurs, if you pass a struct by value and that struct is between 9-16 bytes long: https://bugs.python.org/issue22273

I'm able to reproduce this on python 2.7. Try increasing the size of the struct or use a pointer parameter for the methods.

Unfortunately it seems that this is not fixed until now



来源:https://stackoverflow.com/questions/33563569/abort-when-passing-python-ctypes-struct-containing-array-of-3-ints

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