简体   繁体   English

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

[英]Wrap C Function returning array of unknown size using ctypes python

I am trying to wrap a C function using ctypes, which returns a character array of unknown size. 我试图使用ctypes包装一个C函数,该函数返回未知大小的字符数组。 The function is from the gdal c api , but my question is not specific to that function. 该函数来自gdal c api ,但我的问题并不特定于该函数。

I would like to know if there is a general way of deconstructing the output of a function returning a char** array object of unknown size. 我想知道是否存在解构返回未知大小的char **数组对象的函数输出的一般方法。 In ctypes, this would be POINTER(c_char_p * X) where X is not known. 在ctypes中,这将是POINTER(c_char_p * X) ,其中X未知。

Using the tips from an answer to a similar question , I was able to get the following to work: 使用对类似问题答案中的技巧,我可以使以下内容起作用:

# 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]

Where output is the resulting array and ptr is a ctypes pointer to an open GDALRaster. output是结果数组,而ptr是指向打开的GDALRaster的ctypes指针。 The limitation to this is that I have to construct an array with a fixed length before calling the function. 对此的局限性在于,在调用该函数之前,我必须构造一个具有固定长度的数组。 I can guess what the maximum length could be in practical cases, and simply use that. 我可以猜测实际情况下的最大长度是多少,只需使用即可。 But that is arbitrary, and I wonder if there is a way of getting an array pointer without specifying the array's length. 但这是任意的,我想知道是否存在一种无需指定数组长度即可获取数组指针的方法。 In other words: 换一种说法:

Is there a way to do something similar as the example above, but without specifying an arbitrary maximum length? 有没有一种方法可以执行与上面的示例类似的操作,但不指定任意的最大长度?

It turns out, that you can simply pass a pointer to a c_char_p object without specifying a length as restype argument, if the function output is a null terminated character array. 事实证明,如果函数输出是一个以null终止的字符数组,则只需将指针传递给c_char_p对象, 而无需将长度指定为restype参数。 Then you loop through the result until the null element is found, which indicates the end of the array. 然后循环遍历结果,直到找到null元素为止,该元素指示数组的结尾。

So the following works beatifully for my use case: 因此,以下内容很适合我的用例:

# 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]

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

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