cvRedirectError復活!

OpenCV 2.0 betaにてcvRedirectErrorが使えなくなっていた件ですが、revision2170〜2171にて修正された模様です。いやーよかった。


修正前のcvRedirectErrorの定義は以下の通り。

CV_IMPL CvErrorCallback
cvRedirectError( CvErrorCallback, void*, void** )
{
    return 0;
}

これが、以下のように変わりました。

CV_IMPL CvErrorCallback
cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
{
    return cv::redirectError(errCallback, userdata, prevUserdata);
}

cv名前空間での同名の関数を呼び出しています。OpenCV 2.0では、大概の関数がこのような形でC++向け関数を内部で呼び出すような実装に変わっています。ではcv::redirectErrorを見てみましょう。

CvErrorCallback
redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
{
    if( prevUserdata )
        *prevUserdata = customErrorCallbackData;
    CvErrorCallback prevCallback = customErrorCallback;
    customErrorCallback = errCallback;
    customErrorCallbackData = userdata;
    
    return prevCallback;
}

OpenCV 1.1pre以前でのcvRedirectErrorの定義が大体そのままこちらに移ったという感じです。


このカスタムエラーハンドラを呼び出しているのが以下のcv::errorです。これはOpenCVで何らかのエラーが起こった際に最終的に行きつく関数です。

void error( const Exception& exc )
{
    if (customErrorCallback != 0) 
        customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
                            exc.file.c_str(), exc.line, customErrorCallbackData);
    else
    {
        const char* errorStr = cvErrorStr(exc.code);
        char buf[1 << 16];

        sprintf( buf, "OpenCV Error: %s (%s) in %s, file %s, line %d",
            errorStr, exc.err.c_str(), exc.func.size() > 0 ?
            exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line );
        fprintf( stderr, "%s\n", buf );
        fflush( stderr );
    }
    if(breakOnError)
    {
        static volatile int* p = 0;
        *p = 0;
    }
    throw exc;
}

ということでエラーハンドラは呼び出されるようになったわけですが、困った点が一つあります。関数の一番下で、結局例外はthrowされてしまうのです。すなわちC#からDllImportで呼び出すとSEHExceptionが発生してしまいます。


これを解決するには、全てのDllImportのメソッドをtry-catchで囲ってSEHExceptionを無視するようにするぐらいしか方法が思いつきません。結局労力があまり変わらない恐れが・・・。



static volatile int* p = 0;のあたりはなんだか気になります。どういう意味があるんだろう??コミットログによると、

added custom library handler and the option to passby hard break (via artificial memory access violation) in the error()

ということですが、あまりよく理解していません。




案の定、リリース予定日を過ぎても一向にbetaは取れませんが、大変良いことなのでどんどん更新してほしいものです。