我正在使用swig使用python从C ++库中包装一个类。它总体上起作用,但是有一个异常从库中抛出,我似乎无法在swig界面中捕获它,所以它只是崩溃了python应用程序!
PyMonitor.cc类描述了所需类Monitor的swig接口。 如果无法连接,Monitor的构造函数会抛出异常。我想在PyMonitor中处理这个异常,例如:
PyMonitor.cc:
#include "Monitor.h"
// ...
bool PyMonitor::connect() {
try {
_monitor = new Monitor(_host, _calibration);
} catch (...) {
printf("oops!\n");
}
}
// ...
但是,connect()方法永远不会捕获异常,我只是得到一个“抛出后调用终止...”错误,程序就会中止。
我对swig不太了解,但在我看来,这一切都很好C ++,异常应该在杀死程序之前传播到connect()方法。
有什么想法吗?
答案 0 :(得分:4)
如果要在那里解析它们,则必须将异常转发给Python。 请参阅SWIG Documentation。 为了转发异常,您只需在SWIG接口(.i)文件中添加一些代码。基本上,这可以在.i文件中的任何位置。
此处应指定所有类型的异常,并且SWIG 仅捕获列出的异常类型(在本例中为std :: runtime_error,std :: invalid_argument,std :: out_of_range),所有其他异常被捕获为未知异常(因此正确转发!)。
// Handle standard exceptions.
// NOTE: needs to be before the %import!
%include "exception.i"
%exception
{
try
{
$action
}
catch (const std::runtime_error& e) {
SWIG_exception(SWIG_RuntimeError, e.what());
}
catch (const std::invalid_argument& e) {
SWIG_exception(SWIG_ValueError, e.what());
}
catch (const std::out_of_range& e) {
SWIG_exception(SWIG_IndexError, e.what());
}
catch (...) {
SWIG_exception(SWIG_RuntimeError, "unknown exception");
}
}
答案 1 :(得分:1)
我不熟悉swig,或者一起使用C ++和Python,但如果这是在最新版本的Microsoft Visual C ++下,那么Monitor
类可能会抛出C结构异常,而不是一个C ++类型的异常。 C结构异常不会被C ++异常处理程序捕获,即使是catch(...)
异常处理程序。
如果是这种情况,您可以使用__try/__except
关键字(而不是try/catch
),或使用_set_se_translator
函数将C结构化异常转换为C ++类型异常。< / p>
(旧版本的MSVC ++将C结构化异常视为C ++ int
类型,而 由C ++处理程序捕获,如果我没记错的话。)
如果Microsoft Visual C ++下的不是,那么我不确定这是怎么发生的。
编辑:既然你说这不是MSVC,或许其他东西在你的代码获得它之前捕获异常(并终止程序),或者你的catch块中有什么东西会抛出另一个异常?如果没有更多细节可以使用,那些是我能想到的唯一会导致这些症状的案例。答案 2 :(得分:1)
Monitor constructor
直接或间接调用的函数可能违反了其异常规范,并且不允许抛出std::bad_exception
。如果你没有替换标准函数来捕获它,那么它将解释你所看到的行为。
要测试这个假设,您可以尝试定义自己的处理程序:
void my_unexpected()
{
std::cerr << "Bad things have happened!\n";
std::terminate();
}
bool PyMonitor::connect() {
std::set_unexpected( my_unexpected );
try {
_monitor = new Monitor(_host, _calibration);
} catch (...) {
printf("oops!\n");
}
}
如果你得到“坏事已经发生了!”错误信息然后你已经确认是这种情况,但遗憾的是你可能没有太多可以做的事情。如果你“幸运”,你可能会抛出当前失败的函数的异常规范所允许的my_unexpected
异常,但无论如何都不允许你的意外处理程序正常终止。它必须抛出或以其他方式终止。
要解决此问题,您确实需要进入被调用代码并进行更正,以便不违反异常规范,方法是修复规范本身或修复代码,以便它不会抛出异常不料。
另一种可能性是在抛出原始异常导致的堆栈展开期间抛出异常。这也会导致该过程终止。在这种情况下,虽然您可以替换标准的终止函数,但您没有选择可以中止该程序。终止处理程序不允许抛出或返回,它必须终止程序。