Creating a list of numpy.ndarray of unequal length in Cython
Question: I now have python code to create a list of ndarrays, and these arrays are not
equal length. The piece of code snippet that looks like this:

    
    
    import numpy as np
    from mymodule import list_size, array_length # list_size and array_length are two lists of ints, and the len(array_length) == list_size
    
    ndarray_list = []
    
    for i in range(list_size):
        ndarray_list.append(np.zeros(array_length[i]))
    

Now, I need to convert this to Cython, but do not know how. I tried to create
a 2-d dynamically allocated array, like this:

    
    
    import numpy as np
    cimport numpy as np
    from mymodule import list_size, array_length
    
    cdef int i
    ndarray_list = <double **>malloc(list_size * sizeof(double*))
    for i in range(list_size):
        ndarray_list[i] = <double *>malloc(array_length[i] * sizeof(double))
    

However, this method only creates a double pointer in ndarray_list[i]. I
cannot pass it to other functions which requires some of the ndarray method.

What should I do?


Answer: In order to pass the C `double*` buffer to a function that requires a
`numpy.ndarray` you can create a temporary buffer and assign to its memory
address the address of the `double*` array.

This `malloc()`-based solution is orders of magnitude faster than the other
answer based on NumPy buffers. Note how to `free()` the inner arrays to avoid
a memory leak.

    
    
    import numpy as np
    cimport numpy as np
    from cython cimport view
    from libc.stdlib cimport malloc, free
    
    cdef int i
    cdef double test
    list_size = 10
    ndarray_list = <double **>malloc(list_size * sizeof(double*))
    array_length = <int *>malloc(list_size * sizeof(int*))
    for i in range(list_size):
        array_length[i] = i+1
        ndarray_list[i] = <double *>malloc(array_length[i] * sizeof(double))
        for j in range(array_length[i]):
            ndarray_list[i][j] = j
    
    for i in range(list_size):
        for j in range(array_length[i]):
            test = ndarray_list[i][j]
    
    cdef view.array buff
    for i in range(list_size):
        buff = <double[:array_length[i]]>ndarray_list[i]
        print np.sum(buff)
    
    #...
    
    for i in range(list_size):
        free(ndarray_list[i])
    free(ndarray_list)
    free(array_length)
    

