在Cython中封装std::数组,并将其暴露给内存视图
Wrapping std::array in Cython and Exposing it to memory views
目前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内存视图上循环,比如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
合作的建议都将不胜感激。
编辑:
我现在可以使用以下命令从内存视图转到array2类型:
def __cinit__(self, double[:] mem):
cdef array2 *arr = <array2 *>(&mem[0])
但似乎无论我做什么,我都无法让cython将array2类型转换为内存视图:
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返回到数组的指针会失去作用域,因此会自动销毁数组。一旦我弄清楚如何正确返回数组,我就会尝试更新官方答案。
经过一番努力,我找到了问题的答案。
数组和使用数组的类的定义:
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()
相关文章:
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 视图中的参数推导失败:take_while
- 如何维护资源管理器项目视图中当前可见的项目列表
- 在另一个类视图中添加最多2个图表的正确方法是什么
- OpenVR:向视图方向移动
- 使用 WIN32 API (C/C++) 对特定树视图项进行着色
- 将所选值(通过视图)从 boost::multi_array 复制到另一个数组 (C++)
- 如何在不使用滚动条的情况下使视图更改
- 列表视图更改选择颜色
- Qt - QVector 和模型视图 - 从列表视图获取自定义类的最佳方法是什么?
- 在 Qml 中从 QSqlTableModel 中删除单行时视图不一致
- 如何从未知视图中声明范围::v3::View 变量
- 控制带有信号/插槽的Qt QML滑动视图
- 列表视图项的替代颜色
- 带有 GDB 调试器的 VS 代码内存视图
- 如何将到达图形视图右侧(末端)的QGraphicsPixmapItem移动到左侧(开始)侧(就像在贪吃蛇游戏中发生的事情
- 从资源视图访问对话框时出现问题
- 范围修剪视图实现不适用于反向视图
- 从函数返回范围视图时,带有std::span:中间对象所有权的C++Ranges-v3
- 在Cython中封装std::数组,并将其暴露给内存视图