【发布时间】:2018-05-21 11:58:19
【问题描述】:
使用 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++ 中获取它?
【问题讨论】:
-
这实际上取决于您各自的 ada 和 c++ 编译器如何实现异常。两种语言都以不同的方式指定事物,并且在编译器代码生成和库功能的使用中都需要经过深思熟虑的设计选择,以确保兼容性或至少跨语言边界的一致映射。任何解决方案都将针对特定的编译器集。
-
是的,这个问题也被标记为 gnat。所以它使用 g++/gnat,我会编辑
-
ABI 的世界只是非常缓慢地超越了 C 接口。异常是编译器特定的东西,尽管它们可能遵守平台约定。
-
还发现了这个:
function Get_Exception_Machine_Occurrence (X : Exception_Occurrence) return System.Address; pragma Export (Ada, Get_Exception_Machine_Occurrence,"__gnat_get_exception_machine_occurrence"); -- Get the machine occurrence corresponding to an exception occurrence. It is Null_Address if there is no machine occurrence (in runtimes tha doesn't use GCC mechanism) or if it has been lost (Save_Occurrence doesn't save the machine occurrence). -
我正在与 AdaCore GNAT 维护人员交谈,但他们对此有指导意见:捕获异常,然后调用一些
GNAT.Last_Exception(不记得确切)以获取最后抛出的异常。在多线程环境中并不完美,但大部分时间都可以工作(不幸的是,该功能已损坏,目前正在修复,仅适用于 GNATPro 版本的 beta 版本,因此直到 2019 年才向公众/GPL 提供)跨度>
标签: c++ exception g++ ada gnat