7

I am using Cython (0.15.2) to create an extension for Python (2.6.5). I have created a pxd file and a pyx file. Here are the contents of my pyx file:

cimport capifuncs

cdef class myArray:
    cdef capifuncs.myArray *_my_array
    def __cinit__(self, size):
        self._my_array = capifuncs.array_new(size)
        if (self._my_array is NULL):
            raise MemoryError()

    def __dealloc__(self):
        if self._my_array is not NULL:
            capifuncs.array_free(self._my_array)

    def __bool__(self):
        return not capifuncs.IsEmpty(self._my_array)


    ##############################
    #        Array methods       #
    ##############################

    cpdef getItem(self, unsigned int pos):
        if capifuncs.IsEmpty(self._my_array):
            raise IndexError("Array is empty")
        #if ():
        #    raise IndexError("Array bounds exceeded")

        return capifuncs.array_get_item(self._my_array, pos)


    cpdef setItem(self, unsigned int pos, double val):
        if capifuncs.IsEmpty(self._my_array):
            raise IndexError("Array is empty")
        #if ():
        #    raise IndexError("Array bounds exceeded")

        capifuncs.array_set_item(self._my_array, pos, val)




# Free functions
cpdef long someCAPIFuncCall(capifuncs.FooBar *fb, capifuncs.myArray *arr, long start, long stop):
    return capifuncs.doSomethingInteresting(fb, arr, start, stop)

If I comment out the free (i.e. non-member) function definition statement, the code compiles correctly and the extension is produced. However, if I uncomment it and try to compile the file, I get the following error message:

cafuncs.pyx:64:23: Cannot convert Python object argument to type 'FooBar *'

What is the cause of this, and how do I fix it?

Homunculus Reticulli
  • 65,167
  • 81
  • 216
  • 341

1 Answers1

4

A function defined as cpdef is callable from both Python and C.

If the arguments are declared as C data types, Cython will attempt to automatically convert the objects passed into the function when it's called from Python. But such conversions are only possible for numeric and string types - all other types will result in a compile-time error.

Did you mean to expose this function to Python? If not, define it with cdef.

Otherwise, you will need to create wrappers for the C types that you want to pass to and from Python. See the Cython Tutorials for some examples of how to do this.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • yes, I want to be able to call the C function from Python - the reason for building the extension is to be able to use the data types and functions in the C library, from Python - so, I do need to be able to call the C function from Python, and pass it the C data types (from Python) – Homunculus Reticulli Nov 07 '11 at 19:42
  • Incodentally, if I use cdef instead of cpdef, the code compiles, but I get the following warning message : warning: ‘__pyx_f_6clib_doSomethingInteresting’ defined but not used. Unsuprisingly, when I try to use the function from python, I get the error AttributeError: 'module' object has no attribute 'doSomethingInteresting' – Homunculus Reticulli Nov 07 '11 at 19:47
  • @HomunculusReticulli. See my updated answer. Basically, you need to create wrappers for your C types. – ekhumoro Nov 07 '11 at 19:55
  • I have already created wrappers for my C types - granted I did not show the cdef class for FooBar in the snippet in my question (for brevity sake). – Homunculus Reticulli Nov 07 '11 at 20:27
  • 3
    The problem with the examples in the link is that they only show how to implement object methods - they don't show how to call free (non-member) functions taht accept C data types as arguments. – Homunculus Reticulli Nov 07 '11 at 20:28
  • @HomunculusReticulli. Have you tried `someCAPIFuncCall(capifuncs.FooBar fb, capifuncs.myArray arr, ...`? – ekhumoro Nov 07 '11 at 21:01
  • Yes that was what the original code was like, but I got compilation errors (I can't remember the message). As an aside, whilst I was waiting for an answer to this question, I decided to switch to SWIG. I have since built the module successfully (using SWIG) and am now testing it. – Homunculus Reticulli Nov 07 '11 at 21:27