2017-01-06 7 views
2

J'essaye d'enrouler une fonction C en utilisant ctypes, ce qui retourne un tableau de caractères de taille inconnue. La fonction est from the gdal c api, mais ma question n'est pas spécifique à cette fonction.Retour à la ligne C Fonction renvoyant un tableau de taille inconnue en utilisant ctypes python

Je voudrais savoir s'il existe un moyen général de déconstruire la sortie d'une fonction retournant un objet tableau ** char de taille inconnue. Dans ctypes, ce serait POINTER(c_char_p * X) où X n'est pas connu.

En utilisant les conseils d'un answer to a similar question, j'ai pu obtenir ce qui suit au travail:

# 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 est le tableau résultant et ptr est un pointeur ctypes à un GDALRaster ouvert. La limitation à cela est que je dois construire un tableau avec une longueur fixe avant d'appeler la fonction. Je peux deviner ce que la longueur maximale pourrait être dans des cas pratiques, et simplement l'utiliser. Mais c'est arbitraire, et je me demande s'il existe un moyen d'obtenir un pointeur de tableau sans spécifier la longueur du tableau. En d'autres termes:

Existe-t-il un moyen de faire quelque chose de similaire à l'exemple ci-dessus, mais sans spécifier une longueur maximale arbitraire?

Répondre

0

Il se trouve, que vous pouvez simplement passer un pointeur vers un objet c_char_psans spécifier une longueur comme argument restype, si la sortie de fonction est un tableau de caractères terminé null. Ensuite, vous parcourez le résultat jusqu'à ce que l'élément null soit trouvé, ce qui indique la fin du tableau.

Ainsi, les œuvres suivantes Joliment pour mon cas d'utilisation:

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