2012-04-08 11 views
10

Me gustaría llamar a mi función C desde Python, para manipular algunas matrices NumPy. La función es la siguiente:Envolviendo la función C en Cython y NumPy

void c_func(int *in_array, int n, int *out_array); 

donde los resultados se suministran en out_array, cuyo tamaño Sé de antemano (no es mi función, en realidad). Trato de hacer en el correspondiente .pyx presentar los siguientes, con el fin de poder pasar la entrada a la función de una matriz NumPy, y almacenar el resultado en una matriz NumPy:

def pyfunc(np.ndarray[np.int32_t, ndim=1] in_array):  
    n = len(in_array) 
    out_array = np.zeros((512,), dtype = np.int32) 
    mymodule.c_func(<int *> in_array.data, n, <int *> out_array.data) 
    return out_array 

pero me da "Python objects cannot be cast to pointers of primitive types" error para la asignación de salida. ¿Cómo logro esto?

(Si requiero que la persona que llama Python asigna la matriz de salida adecuada, entonces yo puedo hacer

def pyfunc(np.ndarray[np.int32_t, ndim=1] in_array, np.ndarray[np.int32_t, ndim=1] out_array): 
    n = len(in_array) 
    mymodule.cfunc(<int *> in_array.data, n, <int*> out_array.data) 

Pero puedo hacer esto de una manera que la persona que llama no tiene que asignar previamente la forma apropiada matriz de salida dimensionada?

+1

hicieron intenta proporcionar añadir '' cdef np.ndarray' antes de asignacion out_array'? – Simon

+0

¡Eso funciona, gracias! – Peter

Respuesta

5

Debe añadir cdef np.ndarray antes de la asignacion out_array:

def pyfunc(np.ndarray[np.int32_t, ndim=1] in_array):  
    cdef np.ndarray out_array = np.zeros((512,), dtype = np.int32) 
    n = len(in_array) 
    mymodule.c_func(<int *> in_array.data, n, <int *> out_array.data) 
    return out_array 
0

Aquí hay un ejemplo de cómo manipular matrices NumPy usando código escrito en C/C++ a través de ctypes. Escribí una pequeña función en C, tomando el cuadrado de números de una primera matriz y escribiendo el resultado en una segunda matriz. La cantidad de elementos viene dada por un tercer parámetro. Este código se compila como objeto compartido.

squares.c compilado a squares.so:

void square(double* pin, double* pout, int n) { 
    for (int i=0; i<n; ++i) { 
     pout[i] = pin[i] * pin[i]; 
    } 
} 

en Python, que acaba de cargar la biblioteca utilizando ctypes y llamar a la función. Los punteros de matriz se obtienen de la interfaz NumPy ctypes.

import numpy as np 
import ctypes 

n = 5 
a = np.arange(n, dtype=np.double) 
b = np.zeros(n, dtype=np.double) 

square = ctypes.cdll.LoadLibrary("./square.so") 

aptr = a.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) 
bptr = b.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) 
square.square(aptr, bptr, n) 

print b 

Esto funcionará para cualquier c-biblioteca, sólo hay que saber qué tipos de argumentos para pasar, posiblemente, la reconstrucción de c-estructuras en Python usando ctypes.

+2

Creo que OP quiere usar cython en lugar de ctypes – Simon

Cuestiones relacionadas