这是在ctypes中按值传递结构的正确方法吗?

时间:2014-08-25 14:15:37

标签: python ctypes

我很难使用Python的ctypes调用本机代码,当该struct只包含一个数组时,它会按值传递struct。我在这里做错了吗?以下代码适用于某些类型和数组大小,但会消息带有消息" Aborted (core dumped)"为他人。当结构的大小为16个字节时,它似乎失败了。

这里大概是我正在做的事情(请参阅下面的完整可运行版本):

libsum = ctypes.cdll.LoadLibrary('./libsum.so')

class MyStruct(ctypes.Structure):
    _fields_ = [("data", ctypes.c_uint32 * 4)]

m = MyStruct()

# ... initialize value of m ...

result = libsum.sum(m))

为了调用这样声明的函数:

struct ArrayStruct {
    std::uint32_t data[4];
};

extern "C" int64_t sum(struct ArrayStruct array);

我在64位Ubuntu上运行它并尝试Python 3.4和Python 2.7。在这两种情况下我得到相同的结果 - 只要数组的大小在9到16个字节之间,程序就会中止。

似乎我必须做一些愚蠢的事,但我无法弄清楚是什么。

sum.cpp

#include <cstdint>

using std::size_t;

struct ArrayStruct {
    // We'll define ARRAY_TYPE and ARRAY_SIZE on the
    // command-line when we compile.
    std::ARRAY_TYPE data[ARRAY_SIZE];
};

extern "C" int64_t sum(struct ArrayStruct array)
{
    int64_t acc=0;
    for (size_t i=0; i!=ARRAY_SIZE; ++i)
    {
        acc+=array.data[i];
    }
    return acc;
}

sum.py

import ctypes
import sys

def main():
    array_size = int(sys.argv[1])
    array_type = sys.argv[2]

    libsum = ctypes.cdll.LoadLibrary('./libsum.so')

    ArrType = getattr(ctypes, 'c_' + array_type) * array_size

    class MyStruct(ctypes.Structure):
        _fields_ = [("data", ArrType)]

    m=MyStruct()
    for i in range(array_size):
        m.data[i]=i

    print(libsum.sum(m))

if __name__ == '__main__':
    main()

构建/运行

$ g++ -g -shared -Wall -fPIC sum.cpp -o libsum.so -std=c++11 -D ARRAY_SIZE=16 -D ARRAY_TYPE=uint8_t && python sum.py 16 uint8
Aborted (core dumped)

结果:

                           ARRAY_SIZE
ARRAY_TYPE      1     2     4     8    16    32    64

     uint8      0     1     6    28 crash   496  2016
    uint16      0     1     6 crash   120   496  2016
    uint32      0     1 crash    28   120   496  2016
    uint64      0 crash     6    28   120   496  2016

      int8      0     1     6    28 crash   496  2016
     int16      0     1     6 crash   120   496  2016
     int32      0     1 crash    28   120   496  2016
     int64      0 crash     6    28   120   496  2016

我怀疑这可能是一个错误,我已在此处报告:http://bugs.python.org/issue22273

0 个答案:

没有答案