Reputation: 12653
I'm trying call qsort
in Cython with a custom compare function but I don't understand how to pass the function reference. First, I have a struct:
cdef struct Pair:
int i,j
float h
The compare function sorts by h
:
cdef int compare(const_void *a, const_void *b):
cdef float v = ((<Pair*>a)).h-((<Pair*>b)).h
if v < 0: return -1
if v > 0: return 1
return 0
This is the part I'm having trouble with:
cdef Pair[5] pa
for i in range(5):
pa[i].i = i;
pa[i].j = i*2;
pa[i].h = i*.5;
qsort(pa,5,sizeof(Pair),compare)
The last line won't compile and generates this error which I believe is related to the fact that I can't figure out how to pass compare
as a reference to qsort
:
Cannot assign type 'int (const_void *, const_void *)' to 'int (*)(const_void *, const_void *) nogil'
Upvotes: 15
Views: 6031
Reputation: 13251
I've not been able to reproduce your error. The code you're using is right, and working with Cython 0.15. The only thing i see that might be your error is the "gil" appended to the type. If you want to specifically declare a imported method as "gil safe", append "nogil" at the end of the declaration.
(note that you can check your python code with cython -a , then open web browser for )
cdef extern from "stdlib.h": ctypedef void const_void "const void" void qsort(void *base, int nmemb, int size, int(*compar)(const_void *, const_void *)) nogil cdef struct Pair: int i,j float h cdef int compare(const_void *a, const_void *b): cdef float v = ((a)).h-((b)).h print 'do something with', v if v 0: return 1 return 0 def r(): cdef Pair[5] pa for i in range(5): pa[i].i = i; pa[i].j = i*2; pa[i].h = i*.5; print 'call qsort' qsort(pa,5,sizeof(Pair),compare) print 'call qsort done' r()
This snippet is compiled as:
$ cython --version Cython version 0.15 $ cython --embed test.pyx $ gcc -I/usr/include/python2.7 -Wall -std=c99 test.c -lpython2.7 $ ./a.out call qsort do something with -0.5 do something with -0.5 do something with -0.5 do something with -1.0 do something with -0.5 call qsort done
Upvotes: 9