2014-01-31 18 views
3

目前我正在嘗試使用類型化的memoryview來運行一個結構。例如。鍵入memoryview作爲成員的結構定義

ctypedef struct node: 
    unsigned int[:] inds 

如果inds不是內存視圖,它可以完美地工作,據我所知。然而,在一個memoryview和像

def testFunction(): 
    cdef node testNode 
    testNode.inds = numpy.ones(3,dtype=numpy.uint32) 

使用的東西,我得到一個分割故障。有沒有什麼明顯的我可以忽略或者輸入的記憶體視圖在結構中不起作用?


編輯:

所以我改寫的例子一點點(由於larsman的問題),希望能夠澄清問題一點點:

def testFunction(): 
    cdef node testNode 
    cdef unsigned int[:] tempInds 
    tempInds = numpy.ones(3,dtype=numpy.uintc) 
    testNode.inds = tempInds 

只有最後一行產生一個段錯誤。我不知道如何更詳細地檢查問題。對我來說,它目前看起來像結構不能處理類型化的內存視圖......但希望我失去了一些東西。

我正在使用Cython 0.20(剛剛更新,之前0.19給出了相同的錯誤)。更新的Numpy爲1.8.0。


編輯2:

如果有人有類似問題在未來讀取此:我現在搜索了很多,並不能得到它的工作。除了內存視圖之外,其他所有內容都在工作,我猜它不是(很容易)可能的。 由於方便切割多維數組,我打算使用內存視圖,但顯然它們不適用於結構。現在我在結構中保存一個C指針並將它們轉換爲內存視圖(如果我需要切片)...一個必須非常小心,才能正確訪問數組,但在我的情況下,它似乎工作。如果從現在開始的幾周內,在這個線程中沒有解決的答案,我可能正在爲Cython做一個功能請求。

+0

此segfaults的哪個部分以及哪個Cython版本具有? (順便說一句,'unsigned int'對應''np.uintc',不一定'uint32'。) –

+0

用uintc我可能應該知道。謝謝你的提示。我在原文中添加了一些內容。如果你有任何想法,我可以嘗試,我會很高興聽到他們。 – oli

回答

1

問題來自未初始化的內存,因爲Cython缺少用於原始cdefed結構體的構造函數。當testNode.inds = tempInds賦值時,Cython會嘗試釋放甚至沒有正確初始化的testNode.inds並取消引用隨機指針。

這確實是Cython中的錯誤(請提供!),目前還沒有解決方案(據我所知),但是這裏有一個很糟糕的黑客行爲。

from libc.string cimport memset 

ctypedef struct node: 
    int dummy_hack 
    unsigned int[:] inds 

def testFunction(): 
    cdef node testNode 
    cdef unsigned int[:] tempInds 
    tempInds = numpy.ones(3,dtype=numpy.uintc) 
    # zero init memory to avoid deref garbage 
    memset(&testNode.dummy_hack, 0, sizeof(void*)*4) 
    testNode.inds = tempInds 

僅供參考。 C++中的實際內存視圖對象如下所示(在Cython 21.2上):

MemoryView object is 
__Pyx_memviewslice struct typedef struct { 
    struct __pyx_memoryview_obj *memview; 
    char *data; 
    Py_ssize_t shape[8]; 
    Py_ssize_t strides[8]; 
    Py_ssize_t suboffsets[8]; 
}; 
+0

與你的黑客有關的問題是它會在最後泄漏內存(內存視圖在其生命結束時不會被正確地破壞)。但是,您可以正確識別問題。 – DavidW

相關問題