DLLを作るときの注意事項

WindowsでDLLを作るときには注意事項がいろいろあります。
どの言語で開発するかを問わず必ず問題になるのは、

  • 呼び出し規約
  • DLLヘル
  • メモリの確保と解放
  • 構造体のパディング
  • 例外
  • スタックサイズ
  • FPU制御レジスタ、MXCSRレジスタ

くらいでしょうか。

C++の場合は更に、

  • STLの公開と非互換性
  • クラスの公開
  • オーバーロード

などが追加されます。

ネット上でこれらの問題と解決法(諦めることも含めて)を見つけることはできますが、「FPU制御レジスタ、MXCSR」についてはDLLと絡めた情報は見つかりません。

FPU制御レジスタ、MXCSRレジスタの設定値はコンパイラによって変わります。
FPU制御レジスタの初期値はVCでは0x027f、VB6は0x137f、Delphiは0x1372で全て値が違います。実行中に変えることもできます。
DLLは自分の呼び出し元がどれで作られているかは関知しないので、制御レジスタがどんな値でも対応できなければなりません。

基本的には公開関数の最初で制御レジスタを都合のいい値に変更し、最後で呼び出されたときの値に戻せばOKです。
関数からEXE側にコールバックする等、モジュールを越える場合は都度対応が必要です。

この問題はわかりにくい形で発生します。
以前弊社で利用したOCRライブラリではDelphiからの呼び出しで認識精度がガタ落ちしました。
また弊社PDFDriverに対して16bitのVBアプリからの印刷で例外が出ることがありました。
いずれもFPU制御レジスタの設定で解消できましたが、OCR問題の時はこれを知らなかったのでかなり解決に時間がかかりました。

EXE制作で外部のDLLを利用する場合に、サンプルコード通りなのに結果がおかしい、VCからならOKなのにVC以外からだと同じ入力でも結果が違う、という問題がおきたらFPU制御レジスタを変えると期待通りの動作になるかもしれません。

VCではFPU制御レジスタの初期値は0x027f、MXCSRレジスタの初期値は0x1f80です。