2017-06-08 11 views
-1

cythonのポインタ変数の要素数はどのようにして決められますか?私はCの中で、という変数をポインタが指していると、sizeof(ptr)/sizeof(int)のように見えます。しかし、それはcythonでは動作しないようです。例えば。私はそうのような単一のポインタに二つのメモリビューに参加しようとしたとき:cython - ポインタ変数の項目数を調べる

from libc.stdlib cimport malloc, free 
cdef int * join(int[:] a, int[:] b): 

    cdef: 
     int n_a = a.shape[0] 
     int n_b = b.shape[0] 
     int new_size = n_a + n_b 
     int *joined = <int *> malloc(new_size*sizeof(int)) 
     int i 
    try: 
     for i in range(n_a): 
      joined[i] = a[i] 

     for i in range(n_b): 
      joined[n_a+i] = b[i] 

     return joined 
    finally: 
     free(joined) 

@cython.cdivision(True) 
def join_memviews(int[:] n, int[:] m): 

    cdef int[:] arr_fst = n 
    cdef int[:] arr_snd = m 
    cdef int *arr_new 
    cdef int new_size 

    arr_new = join(arr_fst,arr_snd)  
    new_size = sizeof(arr_new)/sizeof(int) 

    return [arr_new[i] for i in range(new_size)] 

Pythonスクリプトからjoin_memviewsを呼び出すときに、私は、例えば、望ましい結果を得ることはありません。

# in python 
a = np.array([1,2]) 
b = np.array([3,4]) 
a_b = join_memviews(a,b) 

私も使ってみましたタイプ

DTYPE = np.int 
ctypedef np.int_t DTYPE_t 

sizeof()内の引数として、どちらも機能しませんでした。

を編集します。ポインタ変数の処理が明らかに私を不注意にしていました。次のように問題はないと思います(慎重なアプローチではないかもしれませんが)。

cdef int * join(int[:] a, int[:] b, int new_size): 

    cdef: 
     int *joined = <int *> malloc(new_size*sizeof(int)) 
     int i 

    for i in range(n_a): 
     joined[i] = a[i] 

    for i in range(n_b): 
     joined[n_a+i] = b[i] 

    return joined 

def join_memviews(int[:] n, int[:] m): 

    cdef int[:] arr_fst = n 
    cdef int[:] arr_snd = m 
    cdef int *arr_new 
    cdef int new_size = n.shape[0] + m.shape[0] 

    try: 
     arr_new = join(arr_fst,arr_snd, new_size)  

     return [arr_new[i] for i in range(new_size)] 
    finally: 
     free(arr_new) 

答えて

0

できません。 Cでも動作しません。 sizeof(ptr)は、配列の長さではなくポインタを格納するために使用されるメモリの量を返します(通常、システムに応じて4または8)。お使いのアレイの長さは、手動で追跡する必要があるものです。無効なポインタは、呼び出し元の関数に返されるように

cdef int *joined = <int *> malloc(new_size*sizeof(int)) 
try: 
    return joined 
finally: 
    free(joined) 

freeは、関数終了時にすぐに起こる:

は、さらに次のコードは、災害のためのレシピです。


あなたは絶対にそれを避けることができない場合を除きあなたは(numpyのからか、標準ライブラリarrayモジュールのいずれか)を適切に管理Pythonのアレイを使用する必要があります。

+0

これらの説明をいただきありがとうございます。 'try-finally'の部分に関しては、' joined'が解放される前に関数が返す変数にコピーされると考えました。しかし、私はチェックしていないので、警告に感謝します。私はそれが合理的なアプローチではないかもしれませんが、適切に動作するはずのコードを編集します。 – user3820991

+0

編集がうまくいくように見えます。しかし、私はnumpyを使って同じタスクを実行したいと思うでしょう: 'np.concatenate((a、b))' – DavidW

+0

もちろん、2つの配列を結合したいだけならnumpyを使います。私はcythonで実装されたより大きなタスクの中でメモリビューに参加する必要があります。それはかなり起こり、私は[ここ](https://stackoverflow.com/questions/18462785/what-is-the-recommended-way-of-allocating-memory-for-a-typed-memory- view/21054369#21054369)、mallocのアプローチは反復処理を通した迅速な初期化とアクセスを提供するので、私はそのように試してみたかったのです。それでも、私はおそらく最初に、プロファイルよりもセーブしてみるべきです。 – user3820991

関連する問題