2017-07-12 3 views
1

Cythonを使用して書かれたCのカメラドライバへのラッパーを構築しようとしています。私はCythonを新しくしました(2週間前に開始しました)。多くの苦労の後、私は構造体、1D配列のラッパーを開発することができましたが、今は2次元配列が残っています。Cython:Pythonから2D配列をCに渡して取得する

カメラのC APIの1つは、2D配列ポインタを入力として受け取り、キャプチャされた画像を割り当てます。この関数をPythonから呼び出す必要があり、出力イメージをPythonで処理/表示する必要があります。 Cythonのドキュメントやスタックオーバーフローに関するさまざまな記事を読んだ後、私はもっと混乱してしまいました。 Iは、ドライバのAPIルックス(幾分)このようなPythonとCの間の2Dアレイを通過する方法を見つけ出すことができなかった。

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のようなループ変数のタイプを考え出すについてかなり良いですが、私は問題は、それがiの種類を推測することはできませんことを決めたので、それはrow_sizeの種類を推定することができないということだと思いますrange(row_size)から推測されているためです。そのため、temp_mat[i,0]のタイプを推論することはできません。


私はあなたにもあなたもreturn np.array(temp_mat)にreturn文を変更したい疑い - あなたが持っているコードは、おそらくほとんどの時間を動作しますが、時折np.ascontinuousarrayは、コピーを作成する必要がありますし、matは変更されません。

+0

恐ろしい!!!それは働いている!私は 'row_size'を' int'と定義し、それが動作するようになりました。私はこれと過去1週間苦労しています。おそらく、私がCythonで経験した現在のレベルでは、この問題を理解するのに何年もかかりました。ソリューションと説明について@DavidWに感謝します。 – DVS

+0

あなたの説明に基づいて、Cythonコンパイラは変数を定義する必要があると指摘してはいけないと思いますか?コンパイラーがそれを指摘していれば、これはまったく問題にならないでしょう。 – DVS

+0

それは確かに役に立つだろう。 Python変数(例えばタプル)でインデックスを作成したいので、警告を生成する方法が100%明らかではない場合があります。私のロジックについては説明しましょう。将来的にはうまく使うことができます: 'temp_mat [i、0]'がPythonオブジェクトを与えているというエラーメッセージからわかります。最初は、あなたは 'temp_mat'と入力しなかったと思っていました。私がそれを取り除くと、その行の唯一の選択肢は 'i'でした。 – DavidW

関連する問題