EXPORTS

関数またはデータのエクスポート名または序数を指定する 1 つ以上のエクスポート定義のセクションを導入します。 各定義は個別の行に指定する必要があります。

EXPORTS
   definition

解説

最初の definition は、EXPORTS キーワードと同じ行か次の行で指定できます。 .DEF ファイルには、1 つ以上の EXPORTS ステートメントを含めることができます。

エクスポートの definition の構文は次のとおりです。

<エントリ名>[=<内部名>|<他のモジュール>.<エクスポートされる名前>] [@<序数> [NONAME] ] [ [PRIVATE] | [DATA] ]

<エントリ名> は、エクスポートする関数名または変数名です。 この項目は必須です。 エクスポートする名前が DLL 内の名前と異なる場合は、<内部名> を使用して DLL でのエクスポートの名前を指定します。 たとえば、DLL で関数 func1 をエクスポートし、呼び出し元がそれを func2 として使用する場合は、次のように指定します。

EXPORTS
   func2=func1

エクスポートする名前が他のモジュールからのものである場合は、<他のモジュール>.<エクスポートされる名前> を使用して DLL でのエクスポートの名前を指定します。 たとえば、DLL で関数 other_module.func1 をエクスポートし、呼び出し元がそれを func2 として使用する場合は、次のように指定します。

EXPORTS
   func2=other_module.func1

エクスポートする名前が序数でエクスポートする他のモジュールからのものである場合は、<他のモジュール>.#<序数> を使用して DLL でのエクスポートの序数を指定します。 たとえば、DLL で他のモジュールから序数 42 の関数をエクスポートし、呼び出し元がそれを func2 として使用する場合は、次のように指定します。

EXPORTS
   func2=other_module.#42

MSVC コンパイラでは C++ 関数の名前の装飾が使用されるため、装飾名 <内部名> を使用するか、ソース コードで extern "C" を使用してエクスポート関数を定義する必要があります。 コンパイラでは、__stdcall 呼び出し規則を使用する C 関数も、アンダースコア (_) プレフィックスおよびアット マーク (@) とそれに続く引数リストのバイト数 (10 進数) で構成されるサフィックスで装飾されます。

コンパイラによって生成された装飾名を検索するには、DUMPBIN ツールまたは /MAP リンカー オプションを使用します。 装飾名はコンパイラ固有です。 装飾名を .DEF ファイルにエクスポートする場合、DLL にリンクする実行可能ファイルも同じバージョンのコンパイラを使用してビルドする必要があります。 これにより、呼び出し元の装飾名は .DEF ファイルのエクスポート名と一致します。

@<序数> を使用して、関数名ではなく番号が DLL のエクスポート テーブルに格納されるように指定できます。 多くの Windows DLL で、レガシ コードをサポートするために序数がエクスポートされます。 DLL のサイズを最小限に抑えるのに役立つため、16 ビットの Windows コードでは序数を使用することが一般的でした。 レガシ サポートのために DLL のクライアントで必要な場合を除き、関数を序数でエクスポートすることはお勧めしません。 .LIB ファイルには序数と関数のマッピングが含まれているため、DLL を使用するプロジェクトでは通常と同様に関数名を使用できます。

省略可能な NONAME キーワードを使用することで、序数のみでエクスポートして、生成される DLL 内のエクスポート テーブルのサイズを縮小できます。 ただし、DLL で GetProcAddress を使用する場合は、名前が有効でないため、序数がわかっている必要があります。

省略可能なキーワード PRIVATE を使用すると、<エントリ名> は LINK によって生成されるインポート ライブラリに含まれません。 同じく LINK によって生成されるイメージ内のエクスポートには影響しません。

省略可能なキーワード DATA によって、エクスポートがコードではなくデータであることが指定されます。 次の例では、exported_global という名前のデータ変数をエクスポートする方法を示します。

EXPORTS
   exported_global DATA

定義をエクスポートするには 4 つの方法があり、それらを推奨される順序で示します。

  1. ソース コードでの __declspec(dllexport) キーワード

  2. .DEF ファイルでの EXPORTS ステートメント

  3. LINK コマンドでの /EXPORT の指定

  4. ソース コードでの comment ディレクティブ (形式は #pragma comment(linker, "/export: definition "))。 次の例では、関数宣言の前の #pragma コメント ディレクティブを示します。PlainFuncName は関数の非装飾名であり、_PlainFuncName@4 は装飾名です。

    #pragma comment(linker, "/export:PlainFuncName=_PlainFuncName@4")
    BOOL CALLBACK PlainFuncName( Things * lpParams)
    

#pragma ディレクティブは、関数の非修飾名をエクスポートする必要があり、ビルドの構成 (たとえば、32 ビット ビルドか 64 ビット ビルドか) によってエクスポートが異なる場合に便利です。

同じプログラムで 4 つの方法すべてを使用できます。 エクスポートを含むプログラムが LINK によってビルドされる際に、ビルドで .EXP ファイルが使用されていない限り、インポート ライブラリも作成されます。

次に、EXPORTS セクションの例を示します。

EXPORTS
   DllCanUnloadNow      @1          PRIVATE
   DllWindowName = WindowName       DATA
   DllGetClassObject    @4 NONAME   PRIVATE
   DllRegisterServer    @7
   DllUnregisterServer

.DEF ファイルを使用して DLL から変数をエクスポートする場合、変数に __declspec(dllexport) を指定する必要はありません。 ただし、DLL を使用するファイルでは、データの宣言で __declspec(dllimport) を引き続き使用する必要があります。

関連項目

モジュール定義ステートメントに関する規則