无法捕捉异常!

时间:2009-05-27 00:14:38

标签: c++ python exception swig

我正在使用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()方法。

有什么想法吗?

3 个答案:

答案 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异常,但无论如何都不允许你的意外处理程序正常终止。它必须抛出或以其他方式终止。

要解决此问题,您确实需要进入被调用代码并进行更正,以便不违反异常规范,方法是修复规范本身或修复代码,以便它不会抛出异常不料。

另一种可能性是在抛出原始异常导致的堆栈展开期间抛出异常。这也会导致该过程终止。在这种情况下,虽然您可以替换标准的终止函数,但您没有选择可以中止该程序。终止处理程序不允许抛出或返回,它必须终止程序。