【问题标题】:Pass parameter of type pointer to pointer to a C function using ctypes使用 ctypes 将类型指针的参数传递给指向 C 函数的指针
【发布时间】:2020-11-04 14:16:09
【问题描述】:

我的C函数的定义是-

foo(int64_t* total_length,
const int8_t* fromtags,
int64_t fromtagsoffset,
const int32_t* fromindex,
int64_t fromindexoffset,
int64_t length,
int64_t** offsetsraws,
int64_t* offsetsoffsets)

我可以通过ctypesPython 中加载它 -

import ctypes
lib = ctypes.CDLL("....")
name = "foo"
funcC = getattr(lib, name)

我可以设置它需要的参数类型 -

funcC.argtypes = (ctypes.POINTER(ctypes.c_int64), ctypes.POINTER(ctypes.c_int8), ctypes.c_int64, ctypes.POINTER(ctypes.c_int32), ctypes.c_int64, ctypes.c_int64, ctypes.POINTER(ctypes.POINTER(ctypes.c_int64)), ctypes.POINTER(ctypes.c_int64))

我分配要传递给 funcC 的值,例如 -

temparr = [0]*30
total_length = ((ctypes.c_int64)*30)(*temparr)
temparr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
fromtags = ((ctypes.c_int8)*len(temparr))(*temparr)
fromtagsoffset = 1
temparr = [1, 2, 6, 6, 3, 7, 3, 8, 3, 8, 8]
fromindex = ((ctypes.c_int32)*len(temparr))(*temparr)
fromindexoffset = 0
length = 3
temparr = [0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
offsetsoffsets = ((ctypes.c_int64)*len(temparr))(*temparr)

对于类型为指向指针的参数,我分配的值类似于 -

temparr = [1, 2, 1, 2, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
offsetsraws = ctypes.pointer((ctypes.c_int64 * len(temparr))(*temparr))

然后我用参数创建一个list -

testsc = [total_length, fromtags, fromtagsoffset, fromindex, fromindexoffset, length, offsetsraws, offsetsoffsets]

我终于将参数传递给funcC -

funcC(*testsc)

但我得到一个错误 -

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 7: <class 'TypeError'>: expected LP_LP_c_long instance instead of LP_c_long_Array_16

我应该如何解决这个错误?

是不是因为我在将offsetsraws argtype 分配为ctypes.POINTER(ctypes.POINTER(ctypes.c_int64)) 时出错了?

我发现了一个类似的问题 - Python and ctypes: how to correctly pass "pointer-to-pointer" into DLL?,但不同之处在于,在该问题中,传递的指针的指针在输入期间没有分配值,更重要的是,它没有表示为 2D 数组。

【问题讨论】:

    标签: python ctypes


    【解决方案1】:

    上市[Python 3.Docs]: ctypes - A foreign function library for Python

    如果你有一个指向一维数组的指针(~90%+ 种情况),从 int64[]int64* 会做。
    但是,如果您有一个二维数组,事情会变得更加复杂,因为您必须分别处理每个单独的一维数组(行)(例如[SO]: How can i cast a double pointer ctype to numpy array? (@CristiFati's answer)(和其他URL 它引用了))。

    这是前一种情况的示例。

    >>> import ctypes as ct
    >>>
    >>>
    >>> gtc = ct.windll.kernel32.GetTickCount  # This function does NOT take arguments. I used it for DEMO PURPOSES ONLY !!! Basically, it's Undefined Behavior.
    >>> gtc.argtypes = [ct.POINTER(ct.POINTER(ct.c_int64))]
    >>>
    >>> arr = [1, 2, 1, 2, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
    >>>
    >>> arr_ct = ct.pointer((ct.c_int64 * len(arr))(*arr))  # Original variant
    >>>
    >>> gtc(arr_ct)  # Will throw exception
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_LP_c_longlong instance instead of LP_c_longlong_Array_16
    >>>
    >>> arr_ct = ct.pointer(ct.cast((ct.c_int64 * len(arr))(*arr), ct.POINTER(ct.c_int64)))  # cast the (inner) array to pointer
    >>>
    >>> gtc(arr_ct)
    250935781
    

    【讨论】:

      猜你喜欢
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      • 2017-08-09
      • 2023-03-22
      • 1970-01-01
      • 2013-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多