gpt4 book ai didi

python - 在 Cython 中包装 std::array 并将其暴露给内存 View

转载 作者:太空狗 更新时间:2023-10-29 20:55:13 28 4
gpt4 key购买 nike

似乎目前在 Cython 的 repo 中有一个 pull request 来包装 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 内存 View ,比如 double 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 的建议将不胜感激。

编辑:

我现在可以使用以下方法从内存 View 转到 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++ 指针转换为内存 View 。到目前为止,我尝试过的每一种组合都导致了某种类型的类型转换错误。

编辑:我发现我要使用较新版本的 Cython(我使用的是 Cythong 0.22)并升级到 0.23.5 来执行以下语法而不会出错。

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

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

最佳答案

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

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

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

Python 实现

cdef class PyArrayFun:
cdef ArrayFun *thisptr # hold a C++ instance which we're wrapping
def __cinit__(self, int[:] mem):
#
# Conversion from memoryview to std::array<int,4>
#
cdef array4 *arr = <array4 *>(&mem[0])
self.thisptr = new ArrayFun(arr[0])

def getArray(self):
cdef array4 arr = self.thisptr.getArray()
#
# Conversion from std::array<int, 4> to memoryview
#
cdef int[::1] mview = <int[:4]>(&arr[0])
cdef int[::1] new_view = mview.copy()
for i in range(0,4):
print ("arr is ", arr[i])
print("new_view is ", new_view[i])

# A COPY MUST be returned because arr goes out of scope and is
# default destructed when this function exist. Therefore we have to
# copy again. This kinda of sucks because we have to copy the
# internal array out from C++, and then we have to copy the array
# out from Python, therefore 2 copies for one array.
return mview.copy()

关于python - 在 Cython 中包装 std::array 并将其暴露给内存 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36357024/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com