Вызов функции 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.
Ответ 3
Вложение Python в другое приложение может быть полезным.