在Haskell中捕获C++ FFI异常失败

jek*_*jek 7 c++ haskell cabal

在Haskell中使用FFI到C++时,我能够在运行函数时正确捕获异常cabal repl,但在运行时cabal run,不会捕获异常.

展示该问题的简单cabal项目如下:

exception.cabal:

name:                exception
version:             0.1.0.0
build-type:          Simple
cabal-version:       >=1.10
executable exception
  main-is:             Main.hs
  c-sources: main.cxx
  build-depends:       base >=4.7 && <4.8
  default-language:    Haskell2010
  extra-libraries:     stdc++
Run Code Online (Sandbox Code Playgroud)

main.cxx:

# include <exception>
# include <stdexcept>

extern "C" int hs_exception() try
{
  throw std::logic_error("THIS FAILS!");
} catch(...) {
}
Run Code Online (Sandbox Code Playgroud)

Main.hs:

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where

import Foreign.C.Types (CInt(..))


main = print c_hs_exception

foreign import ccall unsafe "hs_exception"
    c_hs_exception :: CInt
Run Code Online (Sandbox Code Playgroud)

REPL(即GHCI)工作:

cabal repl
*Main> main
0
Run Code Online (Sandbox Code Playgroud)

但是在使用GHC编译并运行时失败:

cabal run
libc++abi.dylib: terminating with uncaught exception of type std::logic_error: THIS FAILS!
[1]    12781 abort      cabal run
Run Code Online (Sandbox Code Playgroud)

我的编译器:

? gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix
? ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.8.3
Run Code Online (Sandbox Code Playgroud)

Ony*_*ite 1

这是 Mac 特定的,并被报告为GHC bug 11829。修复方法是将标志-lto_library(LTO = 链接时间优化)传递给 Clang 的链接器。这可以通过 .cabal 文件的可执行部分来完成,如下所示:

executable myprog
  ...
  if os(darwin)
    ld-options: -lto_library
Run Code Online (Sandbox Code Playgroud)

-optl-lto_library或者直接调用时的标志ghc

请注意,这会错误地建议您extra-libraries: to_library改为写入,这是行不通的。