是否有一个首选的方式与c++ std::数组类型在Cython接口?



Cython的libcpp为std::vector这样的容器提供了包装,但对于std::array仍然没有类似的包装。据我所知,这是因为Cython不支持非类型模板参数,所以没有很好的方法来为任意大小的数组创建.pxd(见这里,这里有现有的讨论)。由于这些帖子是几年前的,我想知道在处理std::array类型的首选方法方面是否有任何进展?

举个具体的例子,这是我感兴趣的事情。我有一个c++结构体,它包含数组类型:

%% ex.hpp
#include <array>
struct example{
double a;
int b;
std::array<double, 3> c;
};

和我想做一个cdef类,暴露c与getter和setter,所以我可以设置它与python列表或numpy数组:

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

似乎在这方面没有多大进展。无论如何,我所展示的简单示例实际上提出了一个稍微不同的问题,即如何从python获取/设置扩展类型中包含的std:array类型。使用问题中的链接,我采用了如下的解决方案:

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

第一块给std::arraycython访问特定类型和大小(在这种情况下std::array<double, 3>arrayd3命名),第二块提供了转换函数类型arrayd3 numpy数组首先铸造内存视图,和第三块提供了一个功能类似数组的python对象转换成一个arrayd3类型也通过内存视图。

则示例变为

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)
@c.setter
def c(self, pyArr):
self._cppExample.c = numpyToArrayd3(pyArr)

当然,你需要为数组类型和大小的每一个组合做所有这些,所以它不是理想的。我在回答我自己的问题,所以我在黑暗中摸索,如果有其他的解决方案,请贡献!

最新更新