Python Ctypes传递数据

时间:2018-04-26 13:10:32

标签: python pointers ctypes

我正在访问API并且无法获取返回的数据。两个浮点指针将指向一个数组数组。我必须假设API工作正常。一个不同的函数调用提供了我正在检索的数据的长度。尝试时,此值为length以下。

C函数头

    int function(int, float * data1, float * data2)

ctypes setup

    dll.function.argtypes = (c_int, POINTER(c_float), POINTER(c_float))
    dll.function.restypes = c_int

尝试失败1:

    x = c_float()
    y = c_float()
    status = dll.function(1, byref(x), byref(y))

程序崩溃或访问违规写入。

尝试失败2:

    x = POINTER(c_float)()
    y = POINTER(c_float)()
    status = dll.function(1, x, y)

空指针错误

尝试失败3:

    dll.function.argtypes = (c_int, c_void_p, c_void_p)
    x = c_void_p()
    y = c_void_p()
    status = dll.function(1, x, y)

空指针错误

尝试失败4:

    array = c_float * length
    x = array()
    y = array()
    status = dll.function(1, byref(x), byref(y))

程序崩溃

尝试失败5:

    array = c_float * length
    x = POINTER(array)()
    y = POINTER(array)()
    status = dll.function(1, x, y)

空指针错误或ArgumentError:预期的LP_c_float实例而不是LP_c_float_Array_ [length]

尝试失败6:

    x = (c_float*length)()
    y = (c_float*length)()
    a = cast(x, POINTER(c_float))
    b = cast(y, POINTER(c_float))
    status = dll.function(1, a, b)

程序崩溃

我错过了什么以及为什么?

我相信argtypes是正确的。我试图正确地与他们见面,但仍然存在问题。我需要" malloc"记忆莫名其妙? (我确定在获得数据后我需要自由)。

这是在Windows 7上使用Python 2.7 32位。

我已经查看了其他类似的问题,但我找不到解决方案。我想知道,在这一点上,我是否可以将API归咎于此问题。

2 个答案:

答案 0 :(得分:1)

[Python 3]: Type conversions中解释了处理指针和数组。

我为你准备了一个虚拟的例子。

main.c中

#if defined(_WIN32)
#  define DECLSPEC_DLLEXPORT __declspec(dllexport)
#else
#  define DECLSPEC_DLLEXPORT
#endif


static int kSize = 5;


DECLSPEC_DLLEXPORT int size() {
    return kSize;
}


DECLSPEC_DLLEXPORT int function(int dummy, float *data1, float *data2) {
    for (int i = 0; i < kSize; i++) {
        data1[i] = dummy * i;
        data2[i] = -dummy * (i + 1);
    }
    return 0;
}

code.py

#!/usr/bin/env python

import sys
import ctypes


c_float_p = ctypes.POINTER(ctypes.c_float)


def main():
    dll_dll = ctypes.CDLL("./dll.so")

    size_func = dll_dll.size
    size_func.argtypes = []
    size_func.restype = ctypes.c_int


    function_func = dll_dll.function
    function_func.argtypes = [ctypes.c_int, c_float_p, c_float_p]
    function_func.restype = ctypes.c_int

    size = size_func()
    print(size)

    data1 = (ctypes.c_float * size)()
    data2 = (ctypes.c_float * size)()

    res = function_func(1, ctypes.cast(data1, c_float_p), ctypes.cast(data2, c_float_p))
    for i in range(size):
        print(data1[i], data2[i])


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

备注

  • C 部分试图模仿您的 .dll 所做的事情(或至少我理解的内容):
    • size - 获取数组大小
    • function - 填充数组(直到它们的大小 - 假设它们被调用者正确分配)
  • Python 部分很简单:
    • 加载 .dll
    • 为2个函数定义 argtypes restype (在您的代码中为 restype ' s )(for size_func 没有必要)
    • 获取长度
    • 初始化数组
    • 使用ctypes.cast
    • 将它们传递给 function_func

输出(在 Lnx 上,因为构建 C 代码要简单得多,但可以在 Win 上工作孔):

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050043861]> gcc -shared -o dll.so main.c
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050043861]> python3 code.py
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux

5
0.0 -1.0
1.0 -2.0
2.0 -3.0
3.0 -4.0
4.0 -5.0

答案 1 :(得分:0)

这实际上取决于你使用这些浮点指针做什么。

如果您尝试遍历,即

for(int i = 0; i < size; i++)
    printf("%f\n%, data1[i])

然后肯定这是有问题的,因为没有分配数组。你只需传递一个指向浮点的指针。就是这样。

您需要先分配内存。为此,尝试4看起来更有希望,但我怀疑你的C函数内部有问题导致崩溃。

很难说没有看到该功能的实现。