从C ++处理程序捕获时如何获取Ada异常消息?

时间:2018-05-21 11:58:19

标签: c++ exception g++ ada gnat

使用GNAT Ada和Gnu C ++,我将Ada代码与c ++包装器连接起来,我想在运行这个(愚蠢的)代码时正确捕获Ada异常:

with ada.text_io;

package body ada_throw is

   procedure ada_throw is
   begin
      ada.text_io.put_line ("hello");
      raise program_error;
   end ada_throw;       

end ada_throw;

相关的规范代码是:

package ada_throw is

   procedure ada_throw;
   pragma export (convention => C, entity => ada_throw, external_name => "ada_throw");

end ada_throw;

在C ++方面这样做:

#include <iostream>

extern "C"
{
  void ada_throw();
  void adainit();
}

int main()
{
  adainit();
  ada_throw();
  std::cout << "end of program" << std::endl;
  return 0;
}

我得到了这个:

hello

raised PROGRAM_ERROR : ada_throw.adb:8 explicit raise

所以异常机制有效,我没有得到我的C ++程序的最后一个打印,返回代码是非零的。

现在我想捕获异常。如果我使用catch(...)它可以工作,但我不能再得到明确的错误消息,所以我尝试了这个:

#include <iostream>
#include <cxxabi.h>
extern "C"
{
  void ada_throw();
  void adainit();
}

int main()
{
  adainit();

  try
  {
    ada_throw();
  }
  catch (abi::__foreign_exception const &e)
  {
    std::cout << "exception" << std::endl;        
  }

  std::cout << "end of program" << std::endl;
  return 0;
}

它运作正常,我得到:

hello
exception
end of program

唯一的问题是abi::__foreign_exception没有what()方法,所以我无法掌握有意义的错误消息。

调试程序试图入侵e也是一个死胡同,因为它只是一个具有正确类型的空指针:

(gdb) p &e
$2 = (const __cxxabiv1::__foreign_exception *) 0x0

有没有办法从C ++中获取它?

2 个答案:

答案 0 :(得分:2)

在Ada中,您可以使用函数Ada.Exceptions.Exception_NameAda.Exceptions.Exception_Message获取有关异常事件的信息,这些函数是标准库的一部分。一种选择是为这两个函数提供精简绑定,并在需要有关异常的信息时调用它们。 (究竟如何将abi::__foreign_exception映射到Ada.Exceptions.Exception_ID留给读者练习。)

另一个选择是让Ada编译器明确表示您正在编写C ++,并使用CPlusPlus而不是C作为导出约定。这可能会使编译器提供C ++理解的异常。

这只是一个部分答案,因为我很不习惯使用C ++,但我希望它可以帮助你朝着正确的方向发展。

答案 1 :(得分:2)

根据您在C ++世界中对异常的处理方式,在Ada中编写包装器可能更容易/更清晰,它调用ada_throw并处理任何异常。然后简单地从C ++调用这个包装器。

如果C ++代码必须看到异常并知道发生了什么,那么包装器可以提供类似于what()的方法,并重新引发相同或新的(自定义)异常。 / p>