Вызвать функцию Cython из C++
У меня есть библиотека C++, которая имеет оболочку Python (написано с SWIG). Эта библиотека позволяет выполнять небольшой определяемый пользователем код (обратный вызов), такой как поэлементные операции с вектором. Т.е. вместо просто + вы можете делать любую произвольную двоичную функцию. Прямо сейчас это достигается путем принятия вызываемого объекта Python для двоичной функции и вызова его. Это работает, но примерно в 80 раз медленнее, чем код, который не должен подпрыгивать вверх и вниз в Python на каждой итерации.
Как мне написать / построить / импортировать функцию Cython, которая может быть передана в мою библиотеку C++, чтобы ее можно было вызывать напрямую из библиотеки C++?
Редактировать: Если бы я просто придерживался C, то я бы написал что-то вроде
EWise(double (*callback)(double, double))
EWise бы тогда callback(10, 20);
или такой. я хочу callback
чтобы быть написанным на Cython, используя любое имя пользователя, и указатель на него должен быть как-то передан в мою библиотеку C++ через Python. Это как-то, где я неясно.
3 ответа
Хитрость с Cython заключается в использовании ключевого слова public
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) )
Вы можете достичь этого, делая чистую 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, используемым для содержимого run. Так что он будет работать с вашей библиотекой c.
Встраивание Python в другое приложение может быть полезным для чтения.