共用方式為


交互匯入

匯出或匯入至另一個可執行檔時,匯入是相互的(或迴圈)時,會出現複雜問題。 例如,兩個 DLL 會彼此匯入符號,類似于相互遞迴函式。

相互匯入可執行檔(通常是 DLL)的問題在於,兩者都無法建置,而不需要先建置另一個。 每個建置程式都需要作為輸入,其他建置程式所產生的匯入程式庫。

解決方案是搭配 /DEF 選項使用 LIB 公用程式,其會產生匯入程式庫而不建置可執行檔。 您可以使用這個公用程式來建置您需要的所有匯入程式庫,無論涉及多少 DLL 或相依性有多複雜。

處理相互匯入的一般解決方案為:

  1. 接手每個 DLL。 (任何訂單都是可行的,雖然有些訂單比較理想。如果所有必要的匯入程式庫都存在且為最新狀態,請執行 LINK 來建置可執行檔 (DLL)。 這會產生匯入程式庫。 否則,請執行 LIB 來產生匯入程式庫。

    使用 /DEF 選項執行 LIB 會產生具有 的額外檔案。EXP 擴充功能。 。EXP 檔案必須稍後用來建置可執行檔。

  2. 使用 LINK 或 LIB 建置所有匯入程式庫之後,請返回並執行 LINK 來建置先前步驟中未建置的任何可執行檔。 請注意,必須在 LINK 行上指定對應的 .exp 檔案。

    如果您先前已執行 LIB 公用程式來產生 DLL1 的匯入程式庫,LIB 也會產生 DLL1.exp 檔案。 建置 DLL1.dlll 時,您必須使用 DLL1.exp 作為 LINK 的輸入。

下圖顯示兩個相互匯入 DLL、DLL1 和 DLL2 的解決方案。 步驟 1 是在 DLL1 上執行已設定 /DEF 選項的 LIB。 步驟 1 會產生 DLL1.lib、匯入程式庫和 DLL1.exp。在步驟 2 中,匯入程式庫會用來建置 DLL2,進而產生 DLL2 符號的匯入程式庫。 步驟 3 會建置 DLL1,方法是使用 DLL1.exp 和 DLL2.lib 做為輸入。 請注意,不需要 DLL2 的 .exp 檔案,因為 LIB 不是用來建置 DLL2 的匯入程式庫。

Diagram that shows the inputs and outputs when you use mutual imports to link two DLLs.
連結兩個 DLL 與相互匯入

_AFXEXT的限制

只要您沒有多層 MFC 延伸模組 DLL,您就可以使用 _AFXEXT MFC 延伸模組 DLL 的預處理器符號。 如果您有 MFC 擴充 DLL 呼叫或衍生自您自己的 MFC 延伸模組 DLL,然後衍生自 MFC 類別,您必須使用自己的預處理器符號來避免模棱兩可。

問題是,在 Win32 中,您必須明確宣告任何資料,如同 __declspec(dllexport) 要從 DLL 匯出,如果是 __declspec(dllimport) 從 DLL 匯入資料。 當您定義 _AFXEXT 時,MFC 標頭可確保 已正確定義AFX_EXT_CLASS

當您有多個圖層時,一個符號,例如 AFX_EXT_CLASS 是不夠的,因為 MFC 延伸模組 DLL 可能會匯出新的類別,以及從另一個 MFC 擴充 DLL 匯入其他類別。 若要解決此問題,請使用特殊的預處理器符號,指出您要建置 DLL 本身,而不是使用 DLL。 例如,假設有兩個 MFC 擴充 DLL:A.dll 和 B.dll。 它們分別匯出 A.h 和 B.h 中的某些類別。 B.dll 使用來自 A.dll 的類別。 標頭檔看起來會像這樣:

/* A.H */
#ifdef A_IMPL
   #define CLASS_DECL_A   __declspec(dllexport)
#else
   #define CLASS_DECL_A   __declspec(dllimport)
#endif

class CLASS_DECL_A CExampleA : public CObject
{ ... class definition ... };

// B.H
#ifdef B_IMPL
   #define CLASS_DECL_B   __declspec(dllexport)
#else
   #define CLASS_DECL_B   __declspec(dllimport)
#endif

class CLASS_DECL_B CExampleB : public CExampleA
{ ... class definition ... };
...

建置 A.dll 時,會使用 /D A_IMPL 建置 ,並在建置 B.dll 時使用 建置 /D B_IMPL 。 針對每個 DLL 使用不同的符號, CExampleB 匯出並在 CExampleA 建置 B.dll 時匯入。 CExampleA 在建置 A.dll 時匯出,並在 B.dll 使用時匯入 (或其他用戶端)。

使用內 建AFX_EXT_CLASS _AFXEXT 預處理器符號時,無法完成這種類型的分層。 上述技術在建置其使用中技術、資料庫和網路 MFC 擴充 DLL 時所使用的機制,與 MFC 本身所使用的機制不同。

未匯出整個類別

當您未匯出整個類別時,您必須確定 MFC 宏所建立的必要資料項目已正確匯出。 這可以透過重新定義 AFX_DATA 特定類別的宏來完成。 這應該會在您不匯出整個類別時完成。

例如:

/* A.H */
#ifdef A_IMPL
   #define CLASS_DECL_A  _declspec(dllexport)
#else
   #define CLASS_DECL_A  _declspec(dllimport)
#endif

#undef  AFX_DATA
#define AFX_DATA CLASS_DECL_A

class CExampleA : public CObject
{
   DECLARE_DYNAMIC()
   CLASS_DECL_A int SomeFunction();
   //... class definition ...
};

#undef AFX_DATA
#define AFX_DATA

您想要做什麼事?

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

另請參閱

匯入和匯出