Подтвердить что ты не робот

Как передать указатель на функцию c в Cython?

Я пытаюсь вызвать qsort в Cython с помощью специальной функции сравнения, но я не понимаю, как передать ссылку на функцию. Во-первых, у меня есть структура:

cdef struct Pair:
    int i,j
    float h

Функция сравнения сортируется по 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

Это та часть, с которой у меня возникают проблемы:

    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)

Последняя строка не будет компилироваться и генерирует эту ошибку, которая, как мне кажется, связана с тем, что я не могу понять, как передать compare в качестве ссылки на qsort:

Cannot assign type 'int (const_void *, const_void *)' to 'int (*)(const_void *, const_void *) nogil'
4b9b3361

Ответ 1

Я не смог воспроизвести вашу ошибку. Код, который вы используете, прав, и работает с Cython 0.15. Единственное, что я вижу, это может быть ваша ошибка - это "gil", добавленный к типу. Если вы хотите специально объявить импортированный метод как "gil safe", добавьте "nogil" в конце объявления.

(обратите внимание, что вы можете проверить свой код на питоне с помощью cython -a, затем откройте веб-браузер)

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()

Этот фрагмент скомпилирован как:

$ 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