2016-07-31 5 views
3

2つのCython関数を記述して外部関数をラップしようとしています。関数はお互いの逆関数です。文字列を受け取り、2つのフィールドを持つ構造体を返します.2次元配列へのvoidポインタ(2番目の次元は常に2つの要素:[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], … ])と配列の長さです。もう一方は同じ構造体を受け入れ、文字列を返します。これまでのところ、私は以下を持っています。これはコンパイルされますが、ネストされたリストとの間のキャストは間違いなく間違っています。2Dリストをvoidポインタにキャストして戻す方法

マイ.pxd

cdef extern from "header.h": 
    struct _FFIArray: 
     void* data 
     size_t len 

    cdef _FFIArray decode_polyline_ffi(char* polyline, int precision); 
    cdef char* encode_coordinates_ffi(_FFIArray, int precision); 
    cdef void drop_float_array(_FFIArray coords); 
    cdef void drop_cstring(char* polyline) 

マイ.pyx

import numpy as np 
from pypolyline_p cimport (
    _FFIArray, 
    decode_polyline_ffi, 
    encode_coordinates_ffi, 
    drop_float_array, 
    drop_cstring 
    ) 

def encode_coordinates(coords, int precision): 
    """ coords looks like [[1.0, 2.0], [3.0, 4.0], …] """ 
    cdef double[::1] ncoords = np.array(coords, dtype=np.float64) 
    cdef _FFIArray coords_ffi 
    # Wrong 
    coords_ffi.data = <void*>&ncoords[0] 
    # Wrong 
    coords_ffi.len = ncoords.shape[0] 
    cdef char* result = encode_coordinates_ffi(coords_ffi, precision) 
    cdef bytes polyline = result 
    drop_cstring(result) 
    return polyline 

def decode_polyline(bytes polyline, int precision): 
    cdef char* to_send = polyline 
    cdef _FFIArray result = decode_polyline_ffi(to_send, precision) 
    # Wrong 
    cdef double* incoming_ptr = <double*>(result.data) 
    # Wrong 
    cdef double[::1] view = <double[:result.len:1]>incoming_ptr 
    coords = np.copy(view) 
    drop_float_array(result) 
    return coords 
+1

1つの長さだけを使用して2次元配列を記述しようとしています...どのように他の次元? (それはいつも2ですか?) – DavidW

+0

@davidw申し訳ありませんが、明らかにすべきです:他の次元は常に2つの要素です。 – urschrei

答えて

3

私は問題はあなたが2D配列および1D memoryviews

エンコーディング機能

Inを使用しようとしているということだと思います
# the coords are a 2D, C contiguous array 
    cdef double[:,::1] ncoords = np.array(coords, dtype=np.float64) 
    # ... 
    coords_ffi.data = <void*>&ncoords[0,0] # take the 0,0 element 
    # the rest stays the same 
デコード機能で

# specify it as a 2D, len by 2, C contiguous array 
    cdef double[:,::1] view = <double[:result.len,:2:1]>incoming_ptr 
    # the rest stays the same 

(それはあなたのFFIの機能は、Fortranの連続した配列を期待している可能性があります。この場合、::1はメモリビューの最初の次元に進み、incoming_ptrも変更します)

+0

これは正しいと思います。しかし、インターフェイスを使わずにテストするのは難しいです。 – DavidW

+0

これは完全に機能します。私は、デコード機能のcdefを、 'cdef double [:, :: 1] view = ...'に変更して、エンコード関数のものと一致させました。 – urschrei

+0

良い点 - 私はそれを逃しました。私は正しいので、答えを編集しました(ただし、あなたはすでにあなたがそれを知っている必要はありません! – DavidW

関連する問題