python 遍历动态分配的 Cython 数组

python iterate over dynamically allocated Cython array

我正在为 C class 编写一个 python 包装器,并且我正在使用 PyMem_Malloc 分配内存,如 here

所述
cdef class SomeMemory:

    cdef double* data

    def __cinit__(self, size_t number):
        # allocate some memory (uninitialised, may contain arbitrary data)
        self.data = <my_data_t*> PyMem_Malloc(number * sizeof(my_data_t))
        if not self.data:
            raise MemoryError()

然后我在另一个脚本中导入并使用 class 使用:

import SomeMemory

sm = SomeMemory(10)

我现在想访问 self.data 的元素,但我遇到了 2 个问题

  1. 如果我键入 self.data 并按回车键,ipython 内核会崩溃
  2. 如果我尝试循环自己的数据

喜欢:

for p in self.data:
    print p

我收到一个错误,提示 self.data 不可迭代。

如何访问 self.data?我需要先将元素转换为 my_data_t 吗?

(根据更新的问题进行了大量编辑)

所以 - 我的理解是 self.data 需要声明为 public 才能从 Python:

访问它
cdef class SomeMemory:   
    cdef public double* data
    # also make sure you define __dealloc__ to remove the data

但是,这里似乎没有强制执行。

但是,您真正的问题是 Python 不知道如何处理 double * 类型的对象。它肯定永远不会是可迭代的,因为关于何时停止的信息根本没有存储(所以它总是会结束。

有一系列更好的选择:

代码如下

from cpython cimport array as c_array
from array import array

cdef class SomeMemory:
   cdef c_array.array data

   def __cinit__(self, size_t number):
      self.data = array('d', some initial value goes here)
  • 您将数据存储为 numpy 数组。这可能稍微复杂一些,但具有大致相同的优点。例子就不举例了,比较容易找

  • 您使用 Cython 的类型化内存视图:http://docs.cython.org/src/userguide/memoryviews.html。这样做的好处是它可以让您自己控制内存管理(如果那对您来说 绝对 重要的话)。但是,我不是 100% 确定您可以在 Python 中干净地访问它们(懒得测试!)

  • 您将数据包装在您自己的 class 实现 __getitem____len__ 中,因此它可以用作迭代器。这可能比它值得的麻烦更多。

我推荐第一个选项,除非你有充分的理由选择其他选项。