Wrap C函数使用ctypes python返回未知大小的数组

时间:2017-01-06 09:17:33

标签: python arrays return ctypes gdal

我正在尝试使用ctypes包装C函数,它返回一个未知大小的字符数组。函数是from the gdal c api,但我的问题不是特定于该函数。

我想知道是否有一种解析函数输出的一般方法,返回一个未知大小的char **数组对象。在ctypes中,这将是POINTER(c_char_p * X),其中X未知。

使用answer to a similar question中的提示,我能够完成以下工作:

# Define the function wrapper.
f = ctypes.CDLL('libgdal.so.20').GDALGetMetadata
MAX_OUTPUT_LENGTH = 10
f.restype = ctypes.POINTER(ctypes.c_char_p * MAX_OUTPUT_LENGTH)
f.argtypes = [ctypes.c_void_p, ctypes.c_char_p]

# Example call (the second argument can be null).
result = []
counter = 0
output = f(ptr, None).contents[counter]
while output:
    result.append(output)
    counter += 1
    output = f(ptr, None).contents[counter]

其中output是结果数组,ptr是指向打开的GDALRaster的ctypes指针。对此的限制是我必须在调用函数之前构造一个具有固定长度的数组。我可以猜出在实际情况下最大长度是多少,并且只需使用它。但这是任意的,我想知道是否有一种方法来获取数组指针而不指定数组的长度。换句话说:

有没有办法像上面的例子那样做类似的事情,但没有指定任意的最大长度?

1 个答案:

答案 0 :(得分:0)

事实证明,如果函数输出是一个空终止的字符数组,您只需将指针传递给c_char_p对象而不指定长度作为restype参数。然后循环遍历结果,直到找到null元素,这表示数组的结束。

因此,以下作为我的用例:

# Define the function wrapper, the restype can simply be a
# pointer to c_char_p (without length!).
f = ctypes.CDLL('libgdal.so.20').GDALGetMetadata
f.restype = ctypes.POINTER(ctypes.c_char_p)
f.argtypes = [ctypes.c_void_p, ctypes.c_char_p]

# Prepare python result array.
result = []

# Call C function.
output = f(ptr, None)

# Ensure that output is not a null pointer.
if output:
    # Get first item from array.
    counter = 0
    item = output[counter]
    # Get more items, until the array accessor returns null.
    # The function output (at least in my use case) is a null
    # terminated char array.
    while item:
        result.append(item)
        counter += 1
        item = output[counter]