简体   繁体   English

Python Ctypes 传递数据指针

[英]Python Ctypes passing pointer for data

I am accessing an API and can't get the data returned.我正在访问 API 并且无法获取返回的数据。 The two float pointers will point to an array of data.两个浮点指针将指向一个数据数组。 I must assume the API is working properly.我必须假设 API 工作正常。 A different function call provides a the length of the data I am retrieving.不同的函数调用提供了我正在检索的数据的长度。 This values is length down below when attempted.尝试时,此值的length低于此值。

C Header for Function函数的 C 头文件

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

ctypes setup ctypes 设置

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

Failed Attempt 1:失败的尝试 1:

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

Program crashes OR Access violation writing.程序崩溃或访问冲突写入。

Failed Attempt 2:失败的尝试 2:

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

Null Pointer Error空指针错误

Failed Attempt 3:失败的尝试 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)

Null Pointer Error空指针错误

Failed Attempt 4:失败的尝试 4:

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

Program crashes程序崩溃

Failed Attempt 5:失败的尝试 5:

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

Null Pointer Error OR ArgumentError: expected LP_c_float instance instead of LP_c_float_Array_[length]空指针错误或 ArgumentError:预期的 LP_c_float 实例而不是 LP_c_float_Array_[长度]

Failed Attempt 6:失败的尝试 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)

Program crashes程序崩溃

What am I missing and why?我错过了什么,为什么?

I believe the argtypes are correct.我相信 argtypes 是正确的。 I am attempting to meet them properly, but there continues to be an issues.我试图正确地与他们会面,但仍然存在问题。 Do I need to "malloc" the memory somehow?我需要以某种方式“分配”内存吗? (I'm sure I need to free after I get the data). (我确定我在获得数据后需要释放)。

This is on Windows 7 with Python 2.7 32-bit.这是在带有 Python 2.7 32 位的 Windows 7 上。

I have looked through other similar issues and am not finding a solution.我已经查看了其他类似的问题,但没有找到解决方案。 I am wondering if, at this point, I can blame the API for this issue.我想知道在这一点上,我是否可以将这个问题归咎于 API。

Dealing with pointers and arrays is explained in [Python.Docs]: ctypes - Type conversions . [Python.Docs]: ctypes - Type conversions 中解释了处理指针和数组。

I prepared a dummy example for you.我为你准备了一个虚拟示例。

main00.c :主00.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;
}

code00.py :代码00.py

#!/usr/bin/env python

import sys
import ctypes as ct


c_float_p = ct.POINTER(ct.c_float)


def main(*argv):
    dll = ct.CDLL("./dll00.so")

    size = dll.size
    size.argtypes = []
    size.restype = ct.c_int


    function = dll.function
    function.argtypes = [ct.c_int, c_float_p, c_float_p]
    function.restype = ct.c_int

    sz = size()
    print(sz)

    data1 = (ct.c_float * sz)()
    data2 = (ct.c_float * sz)()

    res = function(1, ct.cast(data1, c_float_p), ct.cast(data2, c_float_p))
    for i in range(sz):
        print(data1[i], data2[i])


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.")
    sys.exit(rc)

Notes :注意事项

  • The C part tries to mimic what your .dll does (or at least what I understood): C部分试图模仿你的.dll做什么(或者至少我理解的):
    • size - gets the arrays sizes size - 获取数组大小
    • function - populates the arrays (till their size - assuming that they were properly allocated by the caller)函数- 填充数组(直到它们的大小 - 假设它们被调用者正确分配)
  • Python part is straightforward: Python部分很简单:
    • Load the .dll加载.dll
    • Define argtypes and restype (in your code it's restype ' s ) for the 2 functions (for size_func not necessary)为 2 个函数定义argtypesrestype (在您的代码中它是restypes )(对于size_func不是必需的)
    • Get the lengths获取长度
    • Initialize the arrays初始化数组
    • Pass them to function_func using ctypes.cast使用ctypes.cast 将它们传递给function_func

Output (on Lnx , as building the C code is much simpler, but works on Win as well):输出(在Lnx 上,因为构建C代码要简单得多,但也适用于Win ):

 [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050043861]> gcc -shared -o dll00.so main00.c [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q050043861]> python3 code00.py Python 3.8.5 (default, Jan 27 2021, 15:41:15) [GCC 9.3.0] 64bit on linux 5 0.0 -1.0 1.0 -2.0 2.0 -3.0 3.0 -4.0 4.0 -5.0

It really depends on what you are doing with these float pointers.这真的取决于你用这些浮点指针做什么。

If you are trying to traverse it, ie如果你试图遍历它,即

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

then for sure this is problematic as no array was allocated.那么肯定这是有问题的,因为没有分配数组。 You simply passed a pointer pointing to a float.您只需传递一个指向浮点数的指针。 That is all.就这些。

You need to first allocate that memory.您需要先分配该内存。 To this end Attempt 4 looks like the more promising, but I suspect you have a problem inside your C function leading to the crash.为此,尝试 4 看起来更有希望,但我怀疑您的 C 函数内部有问题导致崩溃。

Difficult to say without seeing the implementation of that function.如果没有看到该功能的实现,很难说。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM