2017-07-12 113 views
1

我正在嘗試使用Cython在寫入的C中爲相機驅動程序構建一個包裝器。我是Cython的新手(2周前開始)。經過很多努力,我可以成功開發結構,1D陣列的包裝,但現在我堅持使用二維數組。Cython:將二維數組從Python傳遞到C並檢索它

其中一個相機的C API將2D數組指針作爲輸入並將捕獲的圖像指定給它。這個函數需要從Python調用,輸出圖像需要在Python中處理/顯示。在通過Cython文檔和堆棧溢出的各種帖子後,我最終陷入了更多困惑。我無法弄清楚如何通過Python和C.在與二維數組驅動API看起來(有點)像這樣:

driver.h

void assign_values2D(double **matrix, unsigned int row_size, unsigned int column_size); 

c_driver.pyd

cdef extern from "driver.h": 
    void assign_values2D(double **matrix, unsigned int row_size, unsigned int column_size) 

test.pyx

from c_driver import assign_values2D 
import numpy as np 
cimport numpy as np 
cimport cython 
from libc.stdlib cimport malloc, free 
import ctypes 

@cython.boundscheck(False) 
@cython.wraparound(False) 
def assignValues2D(self, np.ndarray[np.double_t,ndim=2,mode='c']mat): 
    row_size,column_size = np.shape(mat) 
    cdef np.ndarray[double, ndim=2, mode="c"] temp_mat = np.ascontiguousarray(mat, dtype = ctypes.c_double) 
    cdef double ** mat_pointer = <double **>malloc(column_size * sizeof(double*)) 
    if not mat_pointer: 
     raise MemoryError 
    try: 
     for i in range(row_size): 
      mat_pointer[i] = &temp_mat[i, 0] 

     assign_values2D(<double **> &mat_pointer[0], row_size, column_size) 
     return np.array(mat) 
    finally: 
     free(mat_pointer) 

test_camera.py

b = np.zeros((5,5), dtype=np.float) # sample code 
print "B Before = " 
print b 
assignValues2D(b) 
print "B After = " 
print b 

在編譯時,它給出了錯誤:

Error compiling Cython file: 
------------------------------------------------------------ 
... 
    if not mat_pointer: 
     raise MemoryError 
    try: 
     for i in range(row_size): 
      mat_pointer[i] = &temp_mat[i, 0] 
       ^
------------------------------------------------------------ 
test.pyx:120:21: Cannot take address of Python variable 

事實上,上面的代碼是從堆棧上溢post截取。我嘗試了其他幾種方法,但都沒有工作。請讓我知道如何將2D圖像轉換爲Python。提前致謝。

+0

我的猜測是,這可能不是編譯提供的第一條錯誤消息,而且以前的錯誤消息可能更具信息性。 – DavidW

+0

但可能問題在於'tmp_mat'被定義爲'np.ndarray [double ...'而不是'np.ndarray [np.double_t ...' – DavidW

+0

感謝@DavidW爲您的快速響應。沒有更早編譯器錯誤。 – DVS

回答

0

您需要輸入i

cdef int i 

(或者,您可以鍵入row_size,它也適用)

一旦知道iint話,就可以制定出索引類型tmp_map給出,所以&運營商工作。


通常它是關於找出循環變量的類型,像i不錯,但我認爲這個問題是它不能推斷的row_size類型,因此決定了它不能推斷的i類型因爲它是從range(row_size)推導出來的。因爲它不能推斷出temp_mat[i,0]的類型。


我懷疑你也你也想return語句改爲return np.array(temp_mat) - 你的代碼可能會工作的大部分時間,但偶爾np.ascontinuousarray將不得不作出一個副本,mat不會改變。

+0

真棒!這是工作!!!。我剛剛將'row_size'定義爲'int'並開始工作。過去1周我一直在努力。也許,憑藉我現在與Cython合作的經驗水平,我需要多年的時間來弄清楚這個問題。感謝@DavidW提供的解決方案和解釋。 – DVS

+0

根據你的解釋,你不覺得Cython編譯器應該指出變量需要被定義嗎?如果編譯器指出,這根本不會成爲問題。 – DVS

+0

這肯定會有幫助。有時候你想用Python變量(例如元組)來索引,所以如何生成警告並不是100%明顯的。讓我解釋一下我的邏輯,以便將來可以使用它:我們從錯誤消息中知道'temp_mat [i,0]'正在給出一個Python對象。起初我以爲你沒有輸入'temp_mat'。一旦我消除了這一點,「我」是該線上唯一的其他選擇。 – DavidW