Passing a numpy pointer (dtype=np.bool) to C++

匿名 (未验证) 提交于 2019-12-03 08:36:05

问题:

I'd like to use a numpy array of type bool in C++ by passing its pointer via Cython. I already know how to do it with other datatypes like uint8. Doing it the same way with boolean it does not work. I am able to compile but there is the following Exception during runtime:

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 ('?') 

Here is my c++ method:

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

The Cython file:

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

And here the python script that calls the method and produces the error:

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

Please let me know if you need more information. Thank you!

回答1:

It looks like the problem is with the array type declaration. According to the documentation at https://cython.readthedocs.org/en/latest/src/tutorial/numpy.html boolean arays aren't yet supported, but you can use them by casting them as arrays of unsigned eight bit integers. Here's a simple example that takes the sum of a 1D array of boolean values (the same as the sum() method would for a boolean NumPy array)

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 

In your C++ code, depending on what you are doing, you may need to cast the pointer back to a bool, I'm not sure on that.

Edit: here's an example of how to cast the pointer in Cython, which should do what you want. I still had to type the array as an unsigned 8 bit integer, but I then cast the pointer back into a 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 

If you want to pass the array in as a pointer, you could just use the following function in your Cython file:

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

Which can be called as

arptr(&A[0]) 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!