« CP2104の誤動作?ZYNQの誤動作? | トップページ | ctypesを使ってPythonからバイナリデータをDLLに入出力する »

2023.08.10

VisualC++でDLLを作るときのランタイムライブラリ/MT /MTd /MD /MDdの指定

長年リリースしていたした「特電Artix-7ボード用のEZ-USB FX3ライブラリ」をPythonで操作できるようにしようとしていたのですが、PythonのctypesでLoadLibraryをしようとしたらエラーが出てしまいました。

Pythonerror

エラーコードらしきものは

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++→コード生成→ランタイムライブラリを開きます。

Mtd

ここにあるマルチスレッド/MTとかいう設定で、DLLにライブラリを埋め込むかどうかを決定します。

まず、マルチスレッド/MTに設定した場合。出来上がったDLLをDependencyWalkerというツールで見てみると、kernel32.dllとSetupapi.dllとuser32.dllを参照していることがわかります。これは開発環境によらずにどのようなPCでもロードできるでしょう。DLLファイルのサイズは140kBくらいでした。

Mt

次に、マルチスレッドデバッグ/MTdを指定した場合。この場合も参照するのはシステムDLLだけなので問題ありません。ファイルのサイズは少し増えて386kByteになりました。

Mtd2

さて、マルチスレッドDLL/MD にした場合ですが、ファイルサイズは43kByteと小さくなったものの、VCRUNTIME140.dllを参照するようになってしまいました。DLLの中からVisual C++ランタイムの部分を省いてシステム共通のDLLを参照するようになったと考えればよいでしょう。また、sprintfなどを使っているのでapi-ms-win-crt-***というDLLも参照するようになりました。

Md

最後は、マルチスレッドデバッグDLL/MDd にした場合ですが、VCRUNTIME140D.dllを必要とするようになりました。ファイルサイズは46kByteくらいです。

Mdd

まとめると、

  • マルチスレッド/MT・・・デバッグ情報なし。ランタイムDLLは埋め込まれる
  • マルチスレッドデバッグ/MTd・・・デバッグ情報あり。ランタイムDLLは埋め込まれる
  • マルチスレッドDLL/MD・・・デバッグ情報なし。ランタイムDLLは別途必要となる
  • マルチスレッドデバッグDLL/MDd・・・デバッグ情報なし。ランタイムDLLは別途必要となる

VCRUNTIME140.dllやVCRUNTIME140D.dllを参照するDLLが出来てしまうと、Pythonや他のアプリから呼び出そうとしたりしたときにファイルが見つからないというエラーが出てしまいかねません。そうならないようにするには、 マルチスレッド/MT か、 マルチスレッドデバッグ/MTd を選択するようにしましょう。

 

|

« CP2104の誤動作?ZYNQの誤動作? | トップページ | ctypesを使ってPythonからバイナリデータをDLLに入出力する »

コメント

コメントを書く



(ウェブ上には掲載しません)




« CP2104の誤動作?ZYNQの誤動作? | トップページ | ctypesを使ってPythonからバイナリデータをDLLに入出力する »