OpenCvSharpをつかう その22 (Dependency Walker)

NuGetでかなり状況は好転したとは思いますが、少し前まででは

OpenCvSharpを使おうと思った人の9割はP/Invokeエラーでつまづき、そのうち7割は脱落

という状態だった、きっとそう思います。

これの(Windowsにおける)特効薬がDependency Walkerです。私はこれがWindowsにおけるもっとも有用なフリーソフトと信じています。

TypeInitializationException等、よくわからない例外でこけたら、以下をお試しください。

OpenCvSharpをつかう 記事一覧

エラーの一例

これを読んでいる方なら、一度、いや何百回と見ているかもしれません。こんな例外を。
f:id:Schima:20140509200316p:plain

最近のバージョンでは、コンソール・Debugウィンドウにこんな表示が出ます。
f:id:Schima:20140509231221p:plain

まずはこのメッセージを読んで、対処してください。お願いします。
以下はそれでもだめだったときです。

Dependency Walkerを使う

こちらからダウンロード。x86x64かは、プログラムの実行環境を考えて選んでください。
http://www.dependencywalker.com/

起動したら、File->Open からDLLを選ぶか、ウィンドウにDLLをドラッグ&ドロップすることで使い始めることができます。以下の画面は「成功例」です。
f:id:Schima:20140509201455p:plain

確認するべきDLL

OpenCvSharpにおいては、PATHを通してあるOpenCVのディレクトリ、または、実行ファイルのあるディレクトリ (VisualStudioなら、[プロジェクト]/bin/Releaseなど)にある以下のDLLを疑ってください。

  • OpenCvSharpExtern.dll
  • opencv_*.dll (opencv_core248.dll など)

失敗例その1 [依存DLLが無い]

f:id:Schima:20140509203531p:plain

ツリーの子ノードとして表示される各DLLが、依存しているDLLです。これが「?」になっているときは、それが無いことを表しています。
いかにもOpenCVのDLLっぽくて、「?」になっているのなら、アウトです。「?」が取れるように頑張ってください。手っ取り早いのは、今チェック中のDLLの隣に「?」の出ているDLLを置いてあげることです。

無視しても良い例

highguiでよくこうなりますが、階層のかなり奥深くで API-MS-WIN-* というようなDLLが「?」になっていたり赤かったりすることがあります。これは私も良くは把握していませんが、実行に影響を与えることは経験的に皆無なので、気にしなくて問題ありません。
f:id:Schima:20140509203035p:plain

失敗例その2

f:id:Schima:20140509202403p:plain

?ではなく、赤くなっています。これは、存在はするが読み込みに問題があるようなときにこうなります。これもアウトなので、赤くなくなるまで頑張ってください。
何が問題かは一概に言えませんが、この図で注目すべきは入力DLLについた64の文字です。つまり64-bit環境向けにビルドされたDLLです。そして赤くなっている依存DLLは、32-bitです。この齟齬から、赤くなっています。

対処としては「?」と同じです。「正しいDLLを見るようにする」ようにDLLを配置してください。この例では、OpenCVのDLLをすべてx64ビルドのものに切り替えます。

失敗例その3

f:id:Schima:20140509204639p:plain

これは全く「?」も赤もないケースです。何がおかしいかと言うと、C/C++ランタイム (msvcr*.dll, msvcp*.dll) のバージョン不一致です。この図が示すのは、OpenCvSharpExtern.dllがmsvcr100.dll に依存していて、OpenCVのDLLがmsvcr110.dll に依存しているという状態です。

解決策としては、OpenCVのDLL側を変えるのが早いです。最近のOpenCVに添付のビルド済みDLLは、vc10, vc11 といった分け方がされています。ビルドしたVC++のバージョンを示していて、C/C++ランタイムのバージョンの差にも直結します。今読み込まれているOpenCVのDLLを、ここから選んで別のDLLに差し替えてみましょう。
f:id:Schima:20140509205128p:plain

なおこの失敗例は最もたちが悪く、バージョンの差があっても問題なく動くこともよくあります。たまにオブジェクトの解放処理でだけクラッシュしたりして気づくものの、原因までたどり着くのは慣れていないと難しいです。

おわりに

OpenCvSharpを公開して6年、もうこの質問に何度答えてきたでしょうか。以後「これを読め」と言って楽をするために書きました。

VisualStudioならNuGetを使ってください。ほとんどのケースでこれとは無縁です。