2017-07-06 8 views
0

J'essaie d'appeler des fonctions d'une bibliothèque C dans python 2.7. Je suis plutôt confus par la plupart des tutoriels ou des informations que j'ai trouvé jusqu'à présent.Python ctypes utilisation des pointeurs de passage

La fonction C prend 3 doubles (étiquetés h, k, l) et 2 pointeurs vers un double (* p, * q) pour résoudre itérativement les deux doubles, initialisés avec 0.0 pour plus de simplicité. La fonction ne renvoie rien, elle utilise simplement les pointeurs pour modifier les valeurs de p et q.

Mon code actuel se lit comme suit:

import ctypes 
path = '/foo/bar.so' 
_lib = ctypes.CDLL(path) 
_lib.solve.argtypes = (ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double)) 

def py_solve(h, k, l): 
    global _lib 
    p, q = ctypes.c_double(0.0), ctypes.c_double(0.0) 
    _lib.solve(ctypes.c_double(h), ctypes.c_double(k), ctypes.c_double(l), ctypes.POINTER(p), ctypes.POINTER(q)) 
    return float(p), float(q) 

je reçois:

'TypeError: must be a ctypes type' 

sur le _lib.solve appelant la ligne (...) dans ma fonction py_solve. Peut-être que ce serait plus simple en utilisant la fonction byef() de ctypes mais je ne sais pas trop comment faire ça. Toute aide est appréciée, merci.

Répondre

1

La fonction ctypes.POINTER prend un argument qui est un ctypes type. Lorsque vous l'utilisez dans la ligne

_lib.solve.argtypes = (ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double)) 

qui est exactement ce que vous faites, car ctypes.c_double est un type .

Lorsque plus tard, vous l'appelez comme ceci:

ctypes.POINTER(p) 

l'argument n'est pas un type, mais un exemple d'un type - une variable déjà initialisé de type ctypes.c_double.

Tout ce que vous devez faire est de créer un pointeur vers les variables déjà initialisées p et q. Il suffit de remplacer ctypes.POINTER(p) par ctypes.byref(p).

+0

Merci. Très bien expliqué, les choses ont du sens maintenant. – MrSwordFish

+0

Notez que 'byref' ne crée pas de pointeur ctypes en soi, contrairement à' ctypes.pointer' ou en instanciant un type de pointeur. 'byref' référence directement le tampon d'un objet ctypes, ce qui est plus efficace que de créer un pointeur ctypes. – eryksun