【问题标题】:python iterate over dynamically allocated Cython arraypython遍历动态分配的Cython数组
【发布时间】:2015-03-21 18:10:55
【问题描述】:

我正在为 C 类编写一个 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()

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

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 吗?

【问题讨论】:

    标签: python c cython dynamic-memory-allocation custom-data-type


    【解决方案1】:

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

    所以 - 我的理解是 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 中干净地访问它们(懒得测试!)

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

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

    【讨论】:

    • 对不起,我没有解释清楚。我的意思是说 self.data 属性似乎在外面不可见
    • 我已经更改了答案以匹配更改后的问题...希望它现在更有用
    • 非常感谢您的冗长解释!
    • 我不知道将 self.data 声明为公开,这将解决部分问题。谢谢!至于您的第二点,我不能只使用 python 数组,因为 my_data_t 实际上是我的 C 代码中的结构,而不是标准数据类型。我猜在这种情况下实现类包装器是唯一的选择?
    • (删除了几个错误的 cmets。)是的,看起来您需要实现一个包含基本迭代函数的小型包装类。 [我认为 memoryviews 对于它们可以接受的类型非常有限。]
    猜你喜欢
    • 2022-06-30
    • 2011-02-25
    • 2020-10-23
    • 2022-09-23
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    相关资源
    最近更新 更多