Je veux appeler la fonction ac de python en utilisant ctypes. Dans la documentation, je ne comprends pas comment passer du pointeur aux vecteurs. La fonction que je veux appeler est:
double f(int n, double* x) { int i; double p=1; for (i=0; i< n; i ++) p = p * x[i]; return p; }
J’ai modifié la fonction avec le pointeur vide, il devient donc f(int, void*)
avec une dissortingbution interne à doubler. Je fais ce qui suit:
def f(x): n = len(x) libc = '/path/to/lib.so' cn = c_int(n) px = pointer(x) cx = c_void_p(px) libc.restype = c_double L = libc.f(cn, cx) return L
Je suppose que x est un tableau numpy, mais je ne suis pas sûr de savoir comment les tableaux numpy sont organisés dans la mémoire et si c’est la meilleure solution.
Modifier:
Aucune des méthodes proposées ne fonctionne avec mon tableau numpy, c’est peut-être dû à la façon dont je définis le tableau:
x = np.array([], 'float64') f = open(file,'r') for line in f: x = np.append(x,float(line))
mais certains d’entre eux fonctionnent si j’ai une liste explicite comme [1,2,3,4,5]
, plutôt qu’une liste qui a été définie ailleurs et qui est référencée comme x
Basé sur la réponse de @Sven Marnach :
#!/usr/bin/env python import ctypes import numpy as np from numpy.ctypeslib import ndpointer libf = ctypes.cdll.LoadLibrary('/path/to/lib.so') libf.f.restype = ctypes.c_double libf.f.argtypes = [ctypes.c_int, ndpointer(ctypes.c_double)] def f(a): return libf.f(a.size, np.ascontiguousarray(a, np.float64)) if __name__=="__main__": # slice to create non-contiguous array a = np.arange(1, 7, dtype=np.float64)[::2] assert not a.flags['C_CONTIGUOUS'] print(a) print(np.multiply.reduce(a)) print(f(a))
[ 1. 3. 5.] 15.0 15.0
Supprimer l’appel np.ascontiguousarray()
produit un résultat incorrect ( 6.0
sur ma machine).
Vous pouvez l’appeler comme ça:
#!python from ctypes import * #!python from ctypes import * # double f(int n, double* x) f = CDLL('/path/to/lib.so').f f.argtypes = [c_int, POINTER(c_double)] f.restype = c_double if __name__ == '__main__': array = (c_double * 5)(1, 2, 3, 4, 5) r = f(len(array), array) print(r)
Si vous avez un tableau numpy, vous pouvez utiliser numpy.array.ctypes.data_as
:
#!python from ctypes import * import numpy # double f(int n, double* x) f = CDLL('/path/to/lib.so').f f.argtypes = [c_int, POINTER(c_double)] f.restype = c_double if __name__ == '__main__': array = numpy.array([1, 2, 3, 4, 5]) r = f(array.size, array.astype(numpy.double).ctypes.data_as(POINTER(c_double))) print(r)
ou:
#!python from ctypes import * import numpy # double f(int n, double* x) f = CDLL('/path/to/lib.so').f f.argtypes = [c_int, POINTER(c_double)] f.restype = c_double if __name__ == '__main__': array = numpy.double([1, 2, 3, 4, 5]) r = f(array.size, array.ctypes.data_as(POINTER(c_double))) print(r)
apparemment j’avais besoin de spécifier le drapeau contigous pour le faire fonctionner
http://scipy-lectures.github.io/advanced/interfacing_with_c/interfacing_with_c.html
c’est un extrait de mon code:
array_1d_double = numpy.ctypeslib.ndpointer(dtype=numpy.double, ndim=1, flags='CONTIGUOUS') libc.f.argtypes = [c_int, array_1d_double] libc.f(n, x)