2012-04-08 22 views
10

Vorrei chiamare la mia funzione C da Python, per manipolare alcuni array di NumPy. La funzione è simile a questo:Funzione C Wrapping in Cython e NumPy

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

in cui i risultati sono forniti in out_array, la cui dimensione lo so in anticipo (non la mia funzione, in realtà). Provo a fare nel corrispondente .pyx depositare seguente, al fine di poter passare l'input della funzione da una matrice NumPy, e memorizzare il risultato in un array 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 

Ma ottenere "Python objects cannot be cast to pointers of primitive types" errore per l'assegnazione dell'output. Come posso realizzare questo?

(Se richiedo che il chiamante Python alloca la matrice di output corretto, allora posso fare

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) 

Ma posso fare questo in modo che il chiamante non deve pre-allocare l'appropriato dimensioni array di uscita?

+1

ha fatto si tenta di fornire aggiungere 'cdef np.ndarray' prima' assegnazione out_array'? – Simon

+0

Funziona, grazie !!! – Peter

risposta

5

Si dovrebbe aggiungere cdef np.ndarray prima della out_array assegnazione:

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

Ecco un esempio come manipolare matrici NumPy utilizzando il codice scritto in C/C++ attraverso ctypes. ho scritto una piccola funzione in C, prendendo il quadrato di numeri da una prima matrice e scrivendo il risultato un secondo array Il numero di elementi è dato da un terzo parametro.Questo codice è compilato come oggetto condiviso

squares.c compilato per squares.so:

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

in Python, è sufficiente caricare la libreria utilizzando ctypes e chiamare la funzione. I puntatori degli array sono ottenuti dall'interfaccia 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 

Questo funziona per qualsiasi c-library, devi solo sapere quali tipi di argomenti da passare, eventualmente, la ricostruzione c-struct in Python usando ctypes.

+2

Penso che l'OP voglia usare cython piuttosto che i ctypes – Simon

Problemi correlati