如何捕获在C函数调用的Haskell回调函数中引发的Haskell异常? [英] How to catch a Haskell exception that is thrown in a Haskell callback function called by a C function?

查看:91
本文介绍了如何捕获在C函数调用的Haskell回调函数中引发的Haskell异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有什么好方法可以捕获由ac函数调用的haskell回调函数引发的haskell异常?

Is there any good way to catch a haskell exception, which is thrown in a haskell callback function called by a c function?

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

For example, let me have a simple c function which just calls a given callback,

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

以及通过ffi使用此功能的haskell代码。

and a haskell code which uses this function via ffi.

{-# 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编译)如下:

The exection result (compiling with GHC 7.8.2) is as follows:

% ./Catch
Catch: AnError "Catch me."

因此,似乎在回调中抛出了异常无法在 main 中捕获。
如何使这种代码正常工作?

So it seems like the exception thrown in callback can not be caught in main. How can I make this kind code work well?

推荐答案

您必须手动执行此操作,这看起来像

You have to do this manually, which would look like this:


  • 在Haskell代码中包装您的回调函数,该函数调用 try ,然后将生成的 Esomeer SomeException()序列化为可以从C处理的格式(可以使用 StablePtr SomeException ,但关键是您需要以某种方式处理 Either )。

  • Wrap your callback function in Haskell code that calls try, and then serializes the resulting Either SomeException () to a format you can process from C (you can use a StablePtr for the SomeException, but the point is that you need to handle the Either somehow).

在您的C代码调用回调的地方,检查结果是否为 Left exn ,如果是,则将错误传播到C代码的顶层,并在此过程中适当地释放资源。此步骤是非机械的,因为C没有异常。

Where your C code calls the callback, check whether the result was a Left exn and if so, propagate the error to the top level of your C code, freeing resources as appropriate along the way. This step is non-mechanical, since C does not have exceptions.

在C代码的顶层,重新序列化异常或结果并读取将其保存在Haskell函数中,该函数包装对C代码的调用,引发异常或适当地返回结果。

At the top level of your C code, re-serialize the exception or result and read it in a Haskell function that wraps your call to the C code, raising an exception or returning the result as appropriate.

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

I'm not aware of any example of a program that does this.

这篇关于如何捕获在C函数调用的Haskell回调函数中引发的Haskell异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆