Как передать указатель на внешнюю программу в Cython

Я пытаюсь написать обертку вокруг программы на C, чтобы я мог вызвать ее из Python. Я использую Cython для этого. Функция C принимает функцию обратного вызова в качестве аргумента, но эта функция обратного вызова будет известна только во время выполнения программы python. Я искал, как это сделать, и кажется, что нет простого решения, но, похоже, работает следующее:

#python.py libc = cdll.LoadLibrary("myfunc.so") #Callback function is defined in myfunc.so .... c_wrapper(libc.fun, ...) 

,

 #c_wrapper.pyx cdef extern void mainfunction(void *F, ...) #The intial C function we are wrapping ctypedef void (*myfuncptr) () def c_wrapper(f, ...) # our function pointer is passed to the wrapper as a Python object cdef myfuncptr thisfunc thisfunc = (<myfuncptr*><size_t>addressof(f))[0] mainfunction(thisfunc, ...) 

Этот метод работает для функций C и FORTRAN (предполагается, что он будет работать для большинства скомпилированных languges) и функций Python (с использованием типов C), но это кажется немного неудобным. Есть ли еще более простой способ сделать это в Китоне?

благодаря

EDIT: я не могу изменить библиотеку C, которую я пытаюсь обернуть

Наверное, ты это знаешь?

Можно ли назвать мой код Python с C?

Ответ: Да, легко. Следуйте примеру в Demos / callback / в дистрибутиве Cython

Итак, зная, что вы можете загрузить свою основную функцию, давайте возьмем другой подход. Я написал несколько глупых функций, чтобы проверить это:

 /* lib.c -> lib.so */ #include <stdio.h> void fn1(void) { puts("Called function 1"); } void fn2(void) { puts("Called function 2"); } 

то функция, которая принимает обратный вызов

 /* main.c -> main.so */ typedef void (*callback)(); void mainfunction(void *F) { ((callback)F)(); } , /* main.c -> main.so */ typedef void (*callback)(); void mainfunction(void *F) { ((callback)F)(); } 

Который может передаваться непосредственно из Python:

 >>> from ctypes import cdll >>> lib = cdll.LoadLibrary('./lib.so') >>> main = cdll.LoadLibrary('./main.so') >>> main.mainfunction(lib.fn1) Called function 1 >>> main.mainfunction(lib.fn2) Called function 2 

И теперь, давайте обернем функцию Python:

 >>> from ctypes import CFUNCTYPE >>> def pyfn(): ... print "Called the Python function" ... >>> CWRAPPER = CFUNCTYPE(None) >>> wrapped_py_func = CWRAPPER(pyfn) >>> main.mainfunction(wrapped_py_func) Called the Python function