VisualC++でDLLを作るときのランタイムライブラリ/MT /MTd /MD /MDdの指定
長年リリースしていたした「特電Artix-7ボード用のEZ-USB FX3ライブラリ」をPythonで操作できるようにしようとしていたのですが、PythonのctypesでLoadLibraryをしようとしたらエラーが出てしまいました。
エラーコードらしきものは
OSError: [WinError -529697949] Windows Error 0xe06d7363
と書かれています。
これが出る原因はDLLが読み込めないからなのですが、その原因としては、
- DLLファイルがみつからない
- 32bitのDLLを64bitのアプリから読もうとしていて何かがおかしい
- 64bitのDLLを32bitのアプリから読もうとしている何かがおかしい
- DLLが別のDLLを参照していて、その参照されるDLLが見つからない
が考えられます。たいていは参照されるDLLが見つからない場合です。
具体的に言うと、Visual C++でプロジェクトを作った場合、デフォルトの設定ではVisualC++のランタイムライブラリのDLLを読み込むように作られてしまいます。そのため、DLLだけを持ってきても開発に使ったPCと異なるPCではロードできないことがよくあります。
こんな基本的なことを忘れたまま、いくつかのプログラムを何年もリリースしっぱなしにしていました・・
他の人に使ってもらうプログラムやライブラリをリリースするならば、ランタイムを埋め込むのが一番です。
そのやり方を説明します。
Visual C++でプロジェクトを右クリックしてプロパティを出し、C/C++→コード生成→ランタイムライブラリを開きます。
ここにあるマルチスレッド/MTとかいう設定で、DLLにライブラリを埋め込むかどうかを決定します。
まず、マルチスレッド/MTに設定した場合。出来上がったDLLをDependencyWalkerというツールで見てみると、kernel32.dllとSetupapi.dllとuser32.dllを参照していることがわかります。これは開発環境によらずにどのようなPCでもロードできるでしょう。DLLファイルのサイズは140kBくらいでした。
次に、マルチスレッドデバッグ/MTdを指定した場合。この場合も参照するのはシステムDLLだけなので問題ありません。ファイルのサイズは少し増えて386kByteになりました。
さて、マルチスレッドDLL/MD にした場合ですが、ファイルサイズは43kByteと小さくなったものの、VCRUNTIME140.dllを参照するようになってしまいました。DLLの中からVisual C++ランタイムの部分を省いてシステム共通のDLLを参照するようになったと考えればよいでしょう。また、sprintfなどを使っているのでapi-ms-win-crt-***というDLLも参照するようになりました。
最後は、マルチスレッドデバッグDLL/MDd にした場合ですが、VCRUNTIME140D.dllを必要とするようになりました。ファイルサイズは46kByteくらいです。
まとめると、
- マルチスレッド/MT・・・デバッグ情報なし。ランタイムDLLは埋め込まれる
- マルチスレッドデバッグ/MTd・・・デバッグ情報あり。ランタイムDLLは埋め込まれる
- マルチスレッドDLL/MD・・・デバッグ情報なし。ランタイムDLLは別途必要となる
- マルチスレッドデバッグDLL/MDd・・・デバッグ情報なし。ランタイムDLLは別途必要となる
VCRUNTIME140.dllやVCRUNTIME140D.dllを参照するDLLが出来てしまうと、Pythonや他のアプリから呼び出そうとしたりしたときにファイルが見つからないというエラーが出てしまいかねません。そうならないようにするには、 マルチスレッド/MT か、 マルチスレッドデバッグ/MTd を選択するようにしましょう。
| 固定リンク
コメント