AFX_EXT_CLASS を使ったエクスポート/インポート
MFC 拡張 DLL では、マクロ AFX_EXT_CLASS を使用してクラスがエクスポートされます。MFC 拡張 DLL にリンクする実行可能ファイルは、このマクロを使用してクラスをインポートします。 AFX_EXT_CLASS マクロでは、MFC 拡張 DLL のビルドに使用されるものと同じヘッダー ファイルを、DLL にリンクする実行可能ファイルと共に使用できます。
DLL のヘッダー ファイルで、次のようにクラスの宣言に AFX_EXT_CLASS キーワードを追加します。
class AFX_EXT_CLASS CMyClass : public CDocument
{
// <body of class>
};
このマクロは、プリプロセッサ シンボル _AFXDLL
と _AFXEXT
が定義されている場合に __declspec(dllexport)
として MFC によって定義されます。 ただし、_AFXDLL
が定義され _AFXEXT
が定義されていない場合、マクロは __declspec(dllimport)
として定義されます。 プリプロセッサ シンボル _AFXDLL
が定義されている場合、MFC の共有バージョンがターゲット実行可能ファイル (DLL またはアプリケーション) によって使用されていることを示します。 _AFXDLL
と _AFXEXT
の両方が定義されている場合、ターゲットの実行可能ファイルが MFC 拡張 DLL であることを示します。
AFX_EXT_CLASS
は、MFC 拡張 DLL からエクスポートするときに __declspec(dllexport)
として定義されているため、.def ファイル内のすべてのクラスのシンボルに装飾名を配置することなく、クラス全体をエクスポートできます。
この方法を使用すると、クラスの .def ファイルとすべての装飾名を作成することは避けられますが、.def ファイルを作成すると、名前を序数でエクスポートできるためより効率的です。 .def ファイル方式のエクスポートを使用する場合は、以下のコードをヘッダー ファイルの先頭と末尾に記述します。
#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// <body of your header file>
#undef AFX_DATA
#define AFX_DATA
注意事項
インライン関数をエクスポートする場合は、バージョンの競合が発生する可能性があるため、注意してください。 インライン関数はアプリケーション コードに展開されます。そのため、後で関数を書き直す場合、アプリケーション自体が再コンパイルされない限り、更新されません。 通常、DLL 関数は、それらを使用するアプリケーションをリビルドせずに更新できます。
クラス内の個々のメンバーのエクスポート
場合によっては、クラスの個々のメンバーをエクスポートする必要があります。 たとえば、CDialog
派生クラスをエクスポートする場合に、コンストラクターと DoModal
呼び出しのエクスポートだけが必要な場合があります。 AFX_EXT_CLASS
は、エクスポートする必要がある個々のメンバーに対して使用できます。
次に例を示します。
class CExampleDialog : public CDialog
{
public:
AFX_EXT_CLASS CExampleDialog();
AFX_EXT_CLASS int DoModal();
...
// rest of class definition
...
};
クラスのすべてのメンバーをエクスポートするわけではないため、MFC マクロの動作方法が理由で、追加の問題が発生する可能性があります。 MFC のヘルパー マクロのいくつかは、実際にデータ メンバーを宣言または定義します。 したがって、これらのデータ メンバーも DLL からエクスポートする必要があります。
たとえば、MFC 拡張 DLL をビルドするときに、DECLARE_DYNAMIC
マクロは次のように定義されます。
#define DECLARE_DYNAMIC(class_name) \
protected: \
static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
static AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
static AFX_DATA
で始まる行は、クラス内の静的オブジェクトを宣言しています。 このクラスを正しくエクスポートし、クライアント実行可能ファイルからランタイム情報にアクセスするには、この静的オブジェクトをエクスポートする必要があります。 静的オブジェクトは修飾子 AFX_DATA
を使用して宣言されているため、DLL をビルドするときには AFX_DATA
が __declspec(dllexport)
になるように定義し、クライアント実行可能ファイルをビルドするときには __declspec(dllimport)
として定義するだけで済みます。 AFX_EXT_CLASS
は既にこの方法で定義されているため、AFX_DATA
を再定義して、クラス定義の AFX_EXT_CLASS
と同じにするだけです。
次に例を示します。
#undef AFX_DATA
#define AFX_DATA AFX_EXT_CLASS
class CExampleView : public CView
{
DECLARE_DYNAMIC()
// ... class definition ...
};
#undef AFX_DATA
#define AFX_DATA
MFC では、マクロ内で定義されているデータ項目に対して常に AFX_DATA
シンボルが使用されるため、この方法はすべてのシナリオで機能します。 たとえば、DECLARE_MESSAGE_MAP
でも機能します。
Note
クラスの選択したメンバーではなくクラス全体をエクスポートする場合は、静的データ メンバーは自動的にエクスポートされます。