1

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)
endofsource
  • 354
  • 5
  • 18
  • 1
    While your question isn't a duplicate of http://stackoverflow.com/questions/23872946/force-numpy-ndarray-to-take-ownership-of-its-memory-in-cython, I think the answers there will be what you want. – DavidW Oct 13 '15 at 17:17
  • 1
    I think ctypes isn't the right approach (and in any case you're misunderstanding `ndpointer`, which is for declaring function interfaces). – DavidW Oct 13 '15 at 17:18
  • 1
    You could also look at http://docs.cython.org/src/userguide/memoryviews.html#cython-arrays for a different approach to the same problem, but if you want a numpy array you'll probably find the first link more helpful. – DavidW Oct 13 '15 at 17:20
  • Acually I just want the c array to be useable (read its content) in my python code. I though numpy would be the way to go. @DavidW – endofsource Oct 13 '15 at 20:50
  • 1
    If that's your main requirement I think the cython array/memoryview approach (in my third comment) is probably the easiest option. – DavidW Oct 13 '15 at 21:07
  • Yes. I used your approach from your third comment. With that it was a no-brainer. Just one line of code. I have no idea how I was unable to realize that before. Thanks a lot! @DavidW – endofsource Oct 14 '15 at 13:08
  • 1
    Good. 2 things: 1) It's more useful to answer yourv own question than edit the answer into the question. 2) Think about how the memory gets freed? I don't think it does in the very simple version you have there... – DavidW Oct 14 '15 at 14:08
  • With my version I'm using the memory of the c-code, correct? All c-arrays I want to access through cython are freed in c at the end of the program. Basically it is just one big array with all the data inside and I want to get the current values from it and do some stuff in python with it (read-only). – endofsource Oct 14 '15 at 14:59
  • 1
    Yes, if you're freeing the arrays yourself in c there is no problem. – DavidW Oct 14 '15 at 15:26

1 Answers1

2

@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.

endofsource
  • 354
  • 5
  • 18