将 Haskell 函数作为 C 代码的回调函数传递

C 函数接受指向其他函数的指针作为参数是很常见的。最常见的示例是设置在某个 GUI 工具包库中单击按钮时要执行的操作。可以将 Haskell 函数作为 C 回调传递。

要调用此 C 函数:

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

我们首先将它导入 Haskell 代码:

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

现在看看如何在 C 头中定义 Object_Event_Cb,定义 Callback 在 Haskell 中的含义:

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

最后,创建一个特殊的函数,将 Callback 类型的 Haskell 函数包装成指针 FunPtr Callback

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

现在我们可以用 C 代码注册回调:

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

取消注册回调后,释放已分配的 FunPtr 非常重要:

freeHaskellFunPtr cbPtr