haskell - 如何捕获在 C 函数调用的 Haskell 回调函数中引发的 Haskell 异常?

标签 haskell exception ffi

有没有什么好的方法可以捕获在 c 函数调用的 haskell 回调函数中抛出的 haskell 异常?

例如,让我有一个简单的 c 函数,它只调用给定的回调,

void callmeback ( void (*callback) () ) {
  callback ();
}

以及通过 ffi 使用此功能的 haskell 代码。
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module Main (main) where

import Foreign
import Control.Exception
import Data.Typeable

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

foreign import ccall safe "callmeback"
        callmeback :: FunPtr (IO ()) -> IO ()

data AnError = AnError String deriving (Show, Eq, Typeable)
instance Exception AnError             

callback :: IO ()
callback = throwIO $ AnError "Catch me."

callMeBack :: IO () -> IO ()
callMeBack f = do fp <- mkCallback f
                  callmeback fp
main = do callMeBack callback `catch`
             (\ e -> do putStrLn $ show (e :: AnError)
                        putStrLn "I caught you." )
          putStrLn "-- Happy end."

执行结果(使用GHC 7.8.2编译)如下:
% ./Catch
Catch: AnError "Catch me."

所以看起来像是 callback 中抛出的异常抓不到main .
我怎样才能使这种代码运行良好?

最佳答案

您必须手动执行此操作,如下所示:

  • 将回调函数包装在调用 try 的 Haskell 代码中, 然后序列化得到的 Either SomeException ()转换为可以从 C 处理的格式(您可以使用 StablePtr 来表示 SomeException,但关键是您需要以某种方式处理 Either)。
  • 在 C 代码调用回调的地方,检查结果是否为 Left exn如果是这样,请将错误传播到 C 代码的顶层,并在此过程中适本地释放资源。这一步是非机械的,因为 C 没有异常。
  • 在 C 代码的顶层,重新序列化异常或结果,并在 Haskell 函数中读取它,该函数将您对 C 代码的调用包装起来,引发异常或根据需要返回结果。

  • 我不知道任何执行此操作的程序示例。

    关于haskell - 如何捕获在 C 函数调用的 Haskell 回调函数中引发的 Haskell 异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29727644/

    相关文章:

    haskell - 为什么 throw 和 throwIO 有区别?

    c++ - 创建接收参数的新异常

    ocaml - 使用它编译C lib和OCaml exe,全部使用ocamlfind

    haskell - 类型安全的稳定指针

    ruby-on-rails - 超时、系统超时和终止符不适用于基于 FFI 的功能

    haskell - ghc 找不到我的 cabal 安装包

    haskell - Haskell Opengl 的光泽度

    haskell - 为 Haskell Platform(标准库)生成 ctag,专门用于 prelude

    程序中的 Java 运行时错误 InputMismatchException

    php - Session::instance() 在 session_start 之后 - Kohana (v.3.2)