Cython's libcpp has wrappers for containers like std::vector
, but still nothing similar for std::array
. As far as I understand, it's because Cython does not have support for non-type template arguments, so there is no nice way to create a .pxd
for arrays of arbitrary size ( See here , and here for existing discussion). Since these posts are from several years ago, I am wondering if there has been any progress in preferred ways to handle std::array
types?
For a concrete example, here's something I'm interested in doing. I have a c++ struct that contains an array type:
%% ex.hpp
#include <array>
struct example{
double a;
int b;
std::array<double, 3> c;
};
and I want to make a cdef
class that exposes c
with a getter and setter so I can set it with a python list or numpy
array:
cdef extern from "ex.hpp":
cdef cppclass example:
double a
int b
<???> c # Not sure what the best option is here
cdef class pyExample:
cdef example *_cppExample
def __cinit__(self):
self._cppExample= new example()
def __dealloc(self):
del self._cppExample
@property
def c(self):
return self._cppExample
@c.setter
def c(self, pyArr):
self._cppExample.c = pyArr
Seems there is not much progress on this front. At any rate, the simple example I showed actually poses a slightly different problem of how to get/set std:array
types contained within an extension type from python. Using the links in the question, I adapted a solution like this:
%% example.pyx
cdef extern from "<array>" namespace "std" nogil:
cdef cppclass arrayd3 "std::array<double, 3>":
arrayd3() except +
double& operator[](size_t)
cdef arrayd3ToNumpy(arrayd3 arr):
cdef double[::1] view = <double[:3]>(&arr[0])
return np.asarray(view.copy())
cdef arrayd3 numpyToArrayd3(nparr):
nparr = np.asarray(nparr, dtype=np.double)
cdef double[:] view = memoryview(nparr)
cdef arrayd3 *arr = <arrayd3 *>(&view[0])
return dereference(arr)
The first block gives cython access to std::array
for a specific type and size (in this case std::array<double, 3>
is named arrayd3) , the second block provides a function for converting type arrayd3 to a numpy array by first casting it to a memory view, and the third block provides a function for converting an array-like python object to an arrayd3 type also via memory views.
Then the example becomes
cdef extern from "ex.hpp":
cdef cppclass example:
double a
int b
arrayd3 c
cdef class pyExample:
cdef example *_cppExample
def __cinit__(self):
self._cppExample= new example()
def __dealloc(self):
del self._cppExample
@property
def c(self):
return arrayd3ToNumpy(self._cppExample)
@c.setter
def c(self, pyArr):
self._cppExample.c = numpyToArrayd3(pyArr)
Of course you need to do all of this for every combination of array type and size so it's less than ideal. And I'm answering my own question so I'm fumbling in the dark here, if there are other solutions please contribute!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.