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