將 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