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は取れませんが、大変良いことなのでどんどん更新してほしいものです。