endofsource
endofsource

Reputation: 354

cython: convert float array to python array with numpy.ctypeslib.ndpointer

I want to use the data from an c array in cython/python code.

To do so I tried to convert the c array with numpy.ctypeslib.ndpointer.
I get the error Cannot convert 'float *' to Python object.

Below is a simple example I tried to get up and running for a couple of days now.

Lets say we have a c function that creates an array. c_code.c

float *compute(int size)
{
    float* array;
    array = malloc(sizeof(float)*size);
    int i;
    for (i=0; i<size; i++)
    {
       array[i] = i;
    }
    return array;
}

In cython I have cython_wrapper.pyx:

# Declare the prototype of the C function we are interested in calling
cdef extern from "c_code.c":
    float*compute(int size)

# Import the Python-level symbols of numpy
import numpy as np

# Import the C-level symbols of numpy
cimport numpy as np
import ctypes

# Numpy must be initialized. When using numpy from C or Cython you must
# _always_ do that, or you will have segfaults
np.import_array()

def py_compute(int size):
    """ Python binding of the 'compute' function in 'c_code.c' that does
        not copy the data allocated in C.
    """
    cdef float *array
    cdef np.ndarray ndarray
    # Call the C function
    array = compute(size)

    func = np.ctypeslib.ndpointer(dtype=ctypes.c_int, shape=(size,))
    ndarray = func(array)
    return ndarray

setup.py:

import numpy
from Cython.Distutils import build_ext


def configuration(parent_package='', top_path=None):
    """ Function used to build our configuration.
    """
    from numpy.distutils.misc_util import Configuration

    # The configuration object that hold information on all the files
    # to be built.
    config = Configuration('', parent_package, top_path)
    config.add_extension('cython_wrapper',
                         sources=['cython_wrapper.pyx'],
                         # libraries=['m'],
                         depends=['c_code.c'],
                         include_dirs=[numpy.get_include()])
    return config


if __name__ == '__main__':
    # Retrieve the parameters of our local configuration
    params = configuration(top_path='').todict()

    # Override the C-extension building so that it knows about '.pyx'
    # Cython files
    params['cmdclass'] = dict(build_ext=build_ext)

    # Call the actual building/packaging function (see distutils docs)
    from numpy.distutils.core import setup

    setup(**params)

Upvotes: 1

Views: 2349

Answers (1)

endofsource
endofsource

Reputation: 354

@DavidW pointed you that numpy.ctypeslib.ndpointer is not the right way to go for what I want to do.

Basically I just want to convert an c-array to an cython/python-array.

With help of this link I found the answer: http://docs.cython.org/src/userguide/memoryviews.html#cython-arrays

def py_compute(int size):
    return <float[:size]> (compute(size))

I'm freeing the memory in c so that I dont have to worry about freeing it in python and therefor can use this really simple solution.

Upvotes: 2

Related Questions