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

问题描述 投票:0回答:2

使用 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++中获取它?

c++ exception g++ ada gnat
2个回答
4
投票

在 Ada 中,您可以使用函数

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

另一个选择是向 Ada 编译器明确表明您正在另一侧编写 C++,并使用

CPP
而不是
C
作为导出约定。 这可能会使编译器提供 C++ 可以理解的异常。

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


3
投票

根据您想要在 C++ 世界中对异常执行的操作,在 Ada 中编写一个包装器可能会更容易/更干净,它调用

ada_throw
并处理任何异常。然后只需从 C++ 调用此包装器即可。

如果 C++ 代码必须看到异常并知道发生了什么,则包装器可以提供类似的

what()
方法,并重新引发相同或新的(自定义)异常。

© www.soinside.com 2019 - 2024. All rights reserved.