2012-03-08 15 views
11

私はBoost.Pythonを使ってPython拡張モジュールを実装しています。モジュールは、Exceptionを継承する独自のカスタム例外クラスを定義する必要があります。それ、どうやったら出来るの?Boost.Pythonカスタム例外クラス

+1

エラーを「例外」から継承させます。 'StandardError'はpython標準ライブラリのツールで生成されるエラーによって使用されます。 – Daenyth

+0

@Daenyth:そうです。私は質問を改訂しました。 – user763305

答えて

12

次の関数は、新しいPython例外クラスを作成し、それを現在のスコープに追加します。モジュール初期化関数で呼び出された場合は、モジュールに追加されます。

最初の引数は、新しい例外クラスの名前です。 2番目の引数は、新しい例外クラスの基本クラスの型オブジェクトです。デフォルトではExceptionの型オブジェクトになります。戻り値は、新しい例外クラスの型オブジェクトです。

PyObject* createExceptionClass(const char* name, PyObject* baseTypeObj = PyExc_Exception) 
{ 
    using std::string; 
    namespace bp = boost::python; 

    string scopeName = bp::extract<string>(bp::scope().attr("__name__")); 
    string qualifiedName0 = scopeName + "." + name; 
    char* qualifiedName1 = const_cast<char*>(qualifiedName0.c_str()); 

    PyObject* typeObj = PyErr_NewException(qualifiedName1, baseTypeObj, 0); 
    if(!typeObj) bp::throw_error_already_set(); 
    bp::scope().attr(name) = bp::handle<>(bp::borrowed(typeObj)); 
    return typeObj; 
} 

次のように関数を使用:

モジュールの初期化関数で関数を呼び出して、グローバル変数に戻り値を格納:

:タイプ MyModule.MyException

PyObject* myExceptionTypeObj = 0; 

BOOST_PYTHON_MODULE(MyModule) 
{ 
    ... 
    myExceptionTypeObj = createExceptionClass("MyException"); 
    ... 
} 

上げる例外

PyErr_SetString(myExceptionTypeObj, "Oh my!") 
+4

'MyException'は実際にはC++型にマップされます。どうすればメンバーを公開できますか? – Barry

-1

@ケニー:

あなたは

PyErr_SetString(myExceptionTypeObj, "Oh my!") 

を参照している場合、私は、「グローバルオブジェクトに文字列をコピーする」としてこれを考えていないでしょう。むしろPythonの内部エラーインジケータを設定して、インタプリタが次のエラーインジケータチェック時にmyExceptionTypeObjのインスタンスを発生させるようにします。

Pythonの例外処理は、(Pythonスレッドごとの)グローバルエラーインジケータで動作します。これは、C APIのafaictを通して例外を発生させる通常の方法です。

私はこの時点でGILを持っていれば、あなたのCコードが入力されたPythonスレッドで例外を正しく発生させることができます。

関連する問題