python迭代动态分配的Cython数组

时间:2015-03-20 00:18:11

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

我正在写一个python包装器到C类,我按照here所解释的那样使用PyMem_Malloc分配内存

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并按Enter键,则ipython内核崩溃
  2. 如果我尝试循环自我数据
  3. 像:

    for p in self.data:
        print p
    

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

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

1 个答案:

答案 0 :(得分:2)

(根据更新的问题严重编辑)

所以 - 我的理解是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__,以便它可以用作迭代器。这可能是值得的麻烦。

我建议使用第一个选项,除非你有充足的理由选择其中一个。