4

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

有什么想法吗?

4

3 回答 3

4

如果要在那里解析异常,则必须将异常转发给 Python。请参阅SWIG 文档。为了转发异常,您只需在 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");
 } 
}
于 2011-09-16T11:21:28.097 回答
1

我不熟悉 swig,也不熟悉同时使用 C++ 和 Python,但如果这是在最新版本的 Microsoft Visual C++ 下,那么Monitor该类可能会抛出 C 结构化异常,而不是 C++ 类型的异常。C 结构化异常不会被 C++ 异常处理程序捕获,即使是catch(...)一个。

如果是这种情况,您可以使用__try/__except关键字(而不是try/catch),或使用该_set_se_translator函数将 C 结构化异常转换为 C++ 类型异常。

(如果我没记错的话,旧版本的 MSVC++ 将 C 结构化异常视为 C++int类型,并被 C++ 处理程序捕获。)

如果这不在Microsoft Visual C++ 下,那么我不确定这是怎么发生的。

编辑:既然你说这不是 MSVC,也许其他东西在你的代码得到它之前捕获异常(并终止程序),或者你的 catch 块中可能有一些东西抛出另一个异常?如果没有更多细节可以处理,这些是我能想到的唯一会导致这些症状的情况。

于 2009-05-27T01:07:33.393 回答
1

监视器直接或间接调用的函数可能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当前失败的函数的异常规范所允许的异常,但无论如何您的意外处理程序都不允许正常终止。它必须抛出或以其他方式终止。

要解决此问题,您确实需要进入被调用代码并更正它以便不违反异常规范,或者通过修复规范本身或修复代码以便它不会抛出意外的异常.

另一种可能性是在堆栈展开期间抛出了一个异常,该异常是由抛出的原始异常引起的。这也会导致进程终止。在这种情况下,虽然您可以替换标准终止功能,但您别无选择,只能中止程序。终止处理程序不允许抛出或返回,它必须终止程序。

于 2009-05-28T07:18:07.440 回答