在Cython中包装std :: array并将其公开给内存视图

时间:2016-04-01 12:59:13

标签: python c++ arrays c++11 cython

似乎在Cython的repo中有一个pull请求来包装c ++ std::array,但在那之前,我可以使用一些帮助。我目前正在包装std::array,如此:

cdef extern from "<array>" namespace "std" nogil:
    cdef cppclass array2 "std::array<double, 2>":
        array2() except+
        double& operator[](size_t)

这有效,但我必须循环遍历cython内存视图,例如,双arr [:],并逐个复制值。有更简单的方法吗?基本上我想做以下事情:

cdef double arr[2]
arr[0] = 1.0
arr[1] = 2.0
cdef array2 array2_arr = arr
#and the reverse
cdef array2 reverse
reverse[0] = 1.0
reverse[1] = 2.0 
cdef double reverse_arr[2] = reverse

这完全不合理吗?因此,使用std::array非常繁琐,因为我有一个for循环将值从cython复制到c ++,从c ++复制到cython。此外,由于cython不能让我们拥有非类型模板参数,我必须为我的代码中std::array的每个变体定义一个包装器。有关如何有效使用std::array的任何建议将不胜感激。

编辑:

我现在可以使用以下内容从内存视图转到array2类型:

def __cinit__(self, double[:] mem):
  cdef array2 *arr = <array2 *>(&mem[0])

但似乎无论我做什么,我都无法通过cython将array2类型转换为memoryview:

cdef array2 arr = self.thisptr.getArray()

# error: '__pyx_t_1' declared as a pointer to a reference of type 'double &'
cdef double[::1] mview = <double[:2]>(&arr[0]) 

#OR

# Stop must be provided to indicate shape
cdef double[::1] mview = <double[::2]>(&arr[0])

请帮我弄清楚如何将C ++指针强制转换为内存视图。我迄今为止尝试的每种组合都会导致某种铸造错误。

编辑: 我发现我使用较新版本的Cython(我使用Cythong 0.22)并升级到0.23.5时执行以下语法,没有错误。

cdef double[::1] mview = <double[:4]>(&arr[0])

但是,如果我尝试从我正在使用的函数返回mview,我会得到垃圾内存。将memoryview返回到我的数组的指针会丢失范围,因此会自动销毁我的数组。一旦我弄清楚如何正确返回我的阵列,我将尝试更新官方答案。

1 个答案:

答案 0 :(得分:3)

经过多次摆弄,我找到了问题的答案。

使用数组的数组和类的定义:

ftp://

Python实现

cdef extern from "<array>" namespace "std" nogil:
  cdef cppclass array4 "std::array<int, 4>":
    array4() except+
    int& operator[](size_t)

cdef extern from "Rectangle.h" namespace "shapes":
  cdef cppclass ArrayFun:
    ArrayFun(array4&)
    array4 getArray()