使用 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 定義時,MFC 會定義這個 __declspec(dllexport) 宏。 但是,宏的定義是當 __declspec(dllimport) 已定義且 _AFXEXT 未定義時 _AFXDLL 。 定義時,預處理器符號 _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 匯出。

例如, DECLARE_DYNAMIC 建置 MFC 擴充 DLL 時,宏的定義如下:

#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

注意

如果您要匯出整個類別,而不是類別的選取成員,則會自動匯出靜態資料成員。

您想要做什麼事?

您還想知道關於哪些方面的詳細資訊?

另請參閱

從 DLL 匯出