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

Jea*_*bre 12 c++ g++ exception 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;
Run Code Online (Sandbox Code Playgroud)

相关规范代码是:

package ada_throw is

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

end ada_throw;
Run Code Online (Sandbox Code Playgroud)

在C++方面这样做:

#include <iostream>

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

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

我明白了:

hello

raised PROGRAM_ERROR : ada_throw.adb:8 explicit raise
Run Code Online (Sandbox Code Playgroud)

所以异常机制的工作,我没有得到我的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;
}
Run Code Online (Sandbox Code Playgroud)

它运作正常,我得到:

hello
exception
end of program
Run Code Online (Sandbox Code Playgroud)

唯一的问题是abi::__foreign_exception没有what()方法,所以我无法得到有意义的错误信息.

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

(gdb) p &e
$2 = (const __cxxabiv1::__foreign_exception *) 0x0
Run Code Online (Sandbox Code Playgroud)

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

Jac*_*sen 3

在 Ada 中,您可以使用函数Ada.Exceptions.Exception_Name和来获取有关异常发生的信息Ada.Exceptions.Exception_Message,这些函数是标准库的一部分。一种选择是为这两个函数提供瘦绑定,并在需要有关异常的信息时调用它们。(具体如何映射abi::__foreign_exceptionAda.Exceptions.Exception_ID留给读者作为练习。)

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

这只是部分答案,因为我对 C++ 非常缺乏实践,但我希望它可以帮助您朝正确的方向发展。

  • `CPlusPlus` 不存在,但 `CPP` 存在:) 现在尝试一下。哎呀,Ada 编译器似乎无法生成正确的 C++ 名称。仍然是相同的“_ada_throw”符号...... (2认同)
  • 支持你的第一个选项,但我怀疑你的替代方案行不通,并且通过删除它可以改进这个答案。 (2认同)