1
votes

I'm trying to register a Python function for callback in a DLL written in C++ and I can't figure out how to do it.

My C++ code header looks like:

extern "C" {
    __declspec(dllexport) void RegisterFunc((void (*)());
 }

And the implementation is:

void (*funcCallback)() = NULL;
__declspec(dllimport) void RegisterFunc(void(*func)())
{
    funcCallback = func;
}

My Cython pyx file looks like:

cdef extern void RegisterFunc(void (*)())

def PyRegisterFunc(func):
    RegisterFunc(func)

When compiled this gives the error message: Cannot convert Python object to 'void (*)(void)'

If I change the code to:

def PyRegisterFunc(func):
    RegisterFunc(<void (*)()>func)

I get the error message: Python objects cannot be cast to pointers of primitive types

I've also tried &func and get the error message: Cannot take address of Python variable.

What is the correct way of passing this Python function as a pointer to my C code?

UPDATE: I should mention my intended purpose for this Python function. The Python application is written in PyQt and the function will emit a signal. The DLL itself has no knowledge of Qt and is compiled without the Qt libraries. A method in the DLL will call this function indirectly which will emit a signal to the Python application.

1
I believe your issue is that your callback function prototype in C does not match a Python style function prototype (which has an argc/argv like mechanism). I have never used cython, I always did it directly linking against python libraries.zmo
If you genuinely want to cast an arbitrary python callable to a c function pointer then you can't do it in Cython (but you can use ctypes/cffi). If you have a single specific function you want to use then make it cdef/cpdef in Cython.DavidW
Document Using C libraries has section Callbacks that might be useful.J.J. Hakala

1 Answers