Haskell Language Foreign Function Interface Passing Haskell functions as callbacks to C code.


It is very common for C functions to accept pointers to other functions as arguments. Most popular example is setting an action to be executed when a button is clicked in some GUI toolkit library. It is possible to pass Haskell functions as C callbacks.

To call this C function:

void event_callback_add (Object *obj, Object_Event_Cb func, const void *data)

we first import it to Haskell code:

foreign import ccall "header.h event_callback_add"
    callbackAdd :: Ptr () -> FunPtr Callback -> Ptr () -> IO ()

Now looking at how Object_Event_Cb is defined in C header, define what Callback is in Haskell:

type Callback = Ptr () -> Ptr () -> IO ()

Finally, create a special function that would wrap Haskell function of type Callback into a pointer FunPtr Callback:

foreign import ccall "wrapper"
    mkCallback :: Callback -> IO (FunPtr Callback)

Now we can register callback with C code:

cbPtr <- mkCallback $ \objPtr dataPtr -> do
    -- callback code
    return ()
callbackAdd cpPtr

It is important to free allocated FunPtr once you unregister the callback:

freeHaskellFunPtr cbPtr