4

swig を使用して、C++ ライブラリのクラスを python でラップしています。それは全体的に機能しますが、ライブラリ内からスローされる例外があり、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 で解析したい場合は、例外を 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

モニターによって直接または間接的に呼び出された関数が、その例外仕様に違反しており、スロー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現在失敗している関数の例外仕様で許可されている例外をスローできる場合がありますが、いずれにせよ、予期しないハンドラーは正常に終了できません。スローするか、終了する必要があります。

これを修正するには、呼び出されたコードに入り、仕様自体を修正するか、予期しない例外をスローしないようにコードを修正して、例外仕様に違反しないように修正する必要があります。 .

もう 1 つの可能性は、スローされた元の例外が原因で、スタックの巻き戻し中に例外がスローされていることです。これにより、プロセスが終了することもあります。この場合、標準の終了関数を置き換えることはできますが、プログラムを中止するしかありません。終了ハンドラーは、スローまたはリターンを許可されていません。プログラムを終了する必要があります。

于 2009-05-28T07:18:07.440 に答える
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 に答える