2013-08-05 21 views
10

Chciałbym użyć typu numpy tablicy bool w C++, przekazując jego wskaźnik za pośrednictwem Cython. Już wiem, jak to zrobić z innymi typami danych, takimi jak uint8. Robiąc to w ten sam sposób z boolowskim, to nie działa. Jestem w stanie skompilować ale jest następujący wyjątek podczas wykonywania:Przekazywanie numpy wskaźnik (dtype = np.bool) do 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 ('?') 

Oto mój C++ metoda:

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

Plik 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) 

I tu skrypt python wywołujący tę metodę i powodujący błąd:

import numpy as np 
import rect 

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

Proszę dać mi znać, jeśli potrzebujesz więcej informacji. Dziękuję Ci!

Odpowiedz

9

Wygląda na to, że problem dotyczy deklaracji typu tablicowego. Zgodnie z dokumentacją pod numerami https://cython.readthedocs.org/en/latest/src/tutorial/numpy.html, wartości logiczne nie są jeszcze obsługiwane, ale można z nich korzystać, przesyłając je jako tablice niepodpisanych ośmio bitowych liczb całkowitych. Oto prosty przykład, który bierze sumę 1D tablicę wartości logicznych (taka sama jak metoda sum() byłoby dla logicznej tablicy numpy)

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 

W swojej kodu C++, w zależności od tego, co robisz, ty może trzeba rzucić wskaźnik z powrotem do boola, nie jestem tego pewien.

Edytuj: oto przykład, jak rzutować wskaźnik w Cython, który powinien zrobić to, co chcesz. Ciągle musiałem wpisać tablicę jako niepodpisaną 8-bitową liczbę całkowitą, ale następnie wrzuciłem wskaźnik z powrotem do wartości logicznej.

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 

Jeśli chcesz przekazać tablicę w postaci wskaźnika, można po prostu użyć następującej funkcji w pliku Cython:

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

który można nazwać jako

arptr(&A[0])