エクスポート方式の使い分け
更新 : 2007 年 11 月
関数のエクスポート方式 (..def ファイルまたは __declspec(dllexport) キーワード) を決めるにあたって、以下の質問に答えてください。
エクスポート関数を引き続き追加する予定ですか。
DLL の利用元は何ですか。たとえば、プログラマがリビルドできない多くの実行形式で使われるサード パーティの DLL ですか。それともプログラマが容易にリビルドできるアプリケーションのみで使われる DLL ですか。
.DEF ファイルを使う場合の利点と欠点
.def ファイルを使って関数をエクスポートすると、エクスポート序数を制御できます。エクスポート関数を DLL に追加する場合、その関数には高い (その他のエクスポート関数よりも高い) 序数値を割り当てることができます。こうすると、暗黙的なリンクを使用するアプリケーションを、新しい関数を含む新しいインポート ライブラリとリンクし直す必要はありません。これが重要になるのは、たとえば、多くのアプリケーションで使うサード パーティの DLL をデザインする場合です。既存のアプリケーションは、新しい DLL を引き続き適切に利用しながら、機能を追加することによって、DLL の機能を向上できます。MFC DLL のビルドには、.def ファイルを使います。
.def ファイルを使うもう 1 つの利点は、NONAME 属性を使って、関数をエクスポートできることです。NONAME 属性は、DLL のエクスポート テーブル内の序数のみを配置します。多数のエクスポート関数を含む DLL の場合、NONAME 属性を使うと、DLL ファイルのサイズを抑えることができます。モジュール定義文の記述については、「モジュール定義ステートメントに関する規則」を参照してください。序数値によるエクスポートの詳細については、「名前ではなく序数値による DLL 関数のエクスポート」を参照してください。
.def ファイルを使う最大の欠点は、C++ ファイル内の関数をエクスポートする場合、コンパイラが関数名を装飾しないように extern "C" を使って標準の C リンケージでエクスポート関数を定義するか、.def ファイルに装飾名を記述する必要があることです。
.def ファイル内に装飾名を配置する場合、装飾名を取得するには、DUMPBIN ツールまたは /MAP リンカ オプションを使います。コンパイラが作成した装飾名は、コンパイラ独自のものであることに注意してください。Visual C++ コンパイラが作成した装飾名を .def ファイルに配置する場合は、DLL とリンクするアプリケーションは、同じバージョンの Visual C++ を使ってビルドする必要があります。これは、呼び出しアプリケーション内の装飾名と、DLL の .def ファイル内のエクスポート名を一致させるためです。
__declspec(dllexport) を使う場合の利点と欠点
__declspec(dllexport) を使うと便利なのは、.def ファイルのメンテナンスやエクスポート関数の装飾名の取得を気にする必要がないことです。このメソッドは、自分で制御するアプリケーションに使用できるよう DLL をデザインする場合などに適しています。新しいエクスポートで DLL をリビルドする場合は、異なるバージョンのコンパイラを使って再コンパイルする際に、エクスポートされた C++ 関数の装飾名が変更されている可能性があるため、アプリケーションもリビルドする必要があります。