2013-08-05 7 views
10

Mi piacerebbe utilizzare una matrice numpy di tipo bool in C++ passando il suo puntatore tramite Cython. So già come farlo con altri tipi di dati come uint8. Farlo allo stesso modo con booleano non funziona. Sono in grado di compilare, ma non c'è la seguente eccezione durante il runtime:Passare un puntatore numerico (dtype = np.bool) a C++

Traceback (most recent call last): 
    File "test.py", line 15, in <module> 
    c = r.count(b, 4) 
    File "rect.pyx", line 41, in rect.PyRectangle.count (rect.cpp:1865) 
    def count(self, np.ndarray[bool, ndim=1, mode="c"] array not None, int size): 
ValueError: Does not understand character buffer dtype format string ('?') 

Ecco il mio C Metodo ++:

void Rectangle::count(bool * array, int size) 
{ 
    for (int i = 0; i < size; i++){ 
     std::cout << array[i] << std::endl; 
    } 
} 

Il file Cython:

# distutils: language = c++ 
# distutils: sources = Rectangle.cpp 

import numpy as np 
cimport numpy as np 

from libcpp cimport bool 

cdef extern from "Rectangle.h" namespace "shapes": 
    cdef cppclass Rectangle: 
     Rectangle(int, int, int, int) except + 
     int x0, y0, x1, y1 
     void count(bool*, int) 

cdef class PyRectangle: 
    cdef Rectangle *thisptr  # hold a C++ instance which we're wrapping 
    def __cinit__(self, int x0, int y0, int x1, int y1): 
     self.thisptr = new Rectangle(x0, y0, x1, y1) 
    def __dealloc__(self): 
     del self.thisptr 

    def count(self, np.ndarray[bool, ndim=1, mode="c"] array not None, int size): 
     self.thisptr.count(&array[0], size) 

E qui lo script python quello chiama il metodo e genera l'errore:

import numpy as np 
import rect 

b = np.array([True, False, False, True]) 
c = r.count(b, 4) 

Per favore fatemi sapere se avete bisogno di ulteriori informazioni. Grazie!

risposta

9

Sembra che il problema sia con la dichiarazione del tipo di matrice. Secondo la documentazione allo https://cython.readthedocs.org/en/latest/src/tutorial/numpy.html, gli arabi booleani non sono ancora supportati, ma è possibile utilizzarli eseguendoli come array di interi a otto bit senza segno. Ecco un semplice esempio che prende la somma di una serie 1D di valori booleani (lo stesso del metodo di sum() farebbe per un allineamento NumPy booleano)

from numpy cimport ndarray as ar 
cimport numpy as np 
cimport cython 

@cython.boundscheck(False) 
@cython.wraparound(False) 
def cysum(ar[np.uint8_t,cast=True] A): 
    cdef int i, n=A.size, tot=0 
    for i in xrange(n): 
     tot += A[i] 
    return tot 

Nel codice C++, a seconda di cosa si sta facendo, è potrebbe essere necessario riportare il puntatore a un bool, non ne sono sicuro.

Modifica: ecco un esempio di come eseguire il cast del puntatore in Cython, che dovrebbe fare ciò che si desidera. Ho ancora dovuto digitare l'array come un numero intero a 8 bit senza segno, ma poi rigiro il puntatore in un bool.

from numpy cimport ndarray as ar 
cimport numpy as np 
from libcpp cimport bool 
cimport cython 

def cysum(ar[np.uint8_t,cast=True] A): 
    cdef int i, n=A.size, tot=0 
    cdef bool *bptr 
    bptr = <bool*> &A[0] 
    for i in xrange(n): 
     tot += bptr[i] 
    return tot 

Se si vuole passare la matrice come un puntatore, si potrebbe utilizzare la seguente funzione nel file Cython:

cdef bool* arptr(np.uint8_t* uintptr): 
    cdef bool *bptr 
    bptr = <bool*> uintptr 
    return bptr 

che può essere chiamato come

arptr(&A[0])