2016-07-31 58 views
3

我正在尝试编写两个用于封装外部函数的Cython函数。这些功能是彼此相反的;一个接受一个字符串,并返回一个带有两个字段的结构体:一个指向二维数组的空指针(第二维总是两个元素:[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], … ])和数组的长度。另一个接受相同的结构,并返回一个字符串。到目前为止,我有以下几点。它编译,但是嵌套列表的转换绝对不正确。如何将2D列表投射到空指针并返回

.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

您试图仅使用一个长度来描述二维数组...您如何期望它知道大小另一个维度? (它总是2?) – DavidW

+0

@davidw对不起,应该已经清楚:其他维度总是2个元素。 – urschrei

回答

3

我认为这个问题是,你正在尝试使用二维数组和1D memoryviews

在编码功能

# 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