Вызов функции Cython из С++

У меня есть библиотека С++ с оболочкой Python (написанная с помощью SWIG). Эта библиотека позволяет выполнять небольшой пользовательский код (обратный вызов), такой как элементарные операции над вектором. То есть вместо просто + вы можете делать любую произвольную двоичную функцию. Сейчас это достигается путем принятия вызываемого объекта Python для двоичной функции и вызова его. Он работает, но примерно в 80 раз медленнее кода, который не должен подпрыгивать вверх и вниз на Python на каждой итерации.

Как мне написать/построить/импортировать функцию Cython можно передать в мою библиотеку С++, чтобы она могла быть вызвана непосредственно библиотекой С++?

Edit: Если бы я просто придерживался C, я бы написал что-то вроде

EWise(double (*callback)(double, double))

EWise будет тогда callback(10, 20); или таковым. Я хочу, чтобы callback записывался в Cython, используя любое имя, которое хочет пользователь, и указатель на него должен быть передан в мою библиотеку С++ через Python. Это почему-то неясно.

Ответы

Ответ 1

Трюк с cython заключается в использовании ключевого слова public p >

cdef public double cython_function( double value, double value2 ):
    return value + value2

Тогда команда cythonize <your_file.pyx> вместе с <your_file.c> создаст заголовок <your_file.h>, который вы можете включить. Кроме того, вы можете сами создать заголовок:

#ifdef __cplusplus {
extern "C"
#endif

double cython_function( double value, double value2 );

#ifdef __cplusplus
}
#endif

Обновление

Затем с небольшим наложением из Python вы можете использовать механизм обратного вызова ctypes

func_type = CFUNCTYPE(c_double, c_double, c_double)

your_library.set_callback_function ( func_type(user_modules.cython_function) )

Ответ 2

Вы можете достичь этого, выполнив чистые cdef функции:

# declare the prototype of your function
ctypedef void (*callback_ptr)(int arg)

# declare your function as cdef
cdef void my_callback(int arg):
    print 'doing some python here', arg

# now, you can use the cdef func as a callback
# in pure C !
cdef void run():
    cdef callback_ptr p = my_callback
    p(42)

if __name__ == '__main__':
    run()

Примечание: вы можете использовать "cython -a", чтобы увидеть, что они не являются кодом на Python для содержимого прогона. Поэтому он будет работать с вашей библиотекой c.