交互匯入
匯出或匯入至另一個可執行檔時,匯入是相互的(或迴圈)時,會出現複雜問題。 例如,兩個 DLL 會彼此匯入符號,類似於相互遞歸函式。
相互匯入可執行檔(通常是 DLL)的問題在於,兩者都無法建置,而不需要先建置另一個。 每個建置程式都需要作為輸入,其他建置程式所產生的匯入連結庫。
解決方案是搭配 /DEF 選項使用 LIB 公用程式,其會產生匯入連結庫而不建置可執行檔。 您可以使用這個公用程式來建置您需要的所有匯入連結庫,無論涉及多少 DLL 或相依性有多複雜。
處理相互匯入的一般解決方案為:
接手每個 DLL。 (任何訂單都是可行的,雖然有些訂單比較理想。如果所有必要的匯入連結庫都存在且為最新狀態,請執行LINK來建置可執行檔 (DLL)。 這會產生匯入連結庫。 否則,請執行 LIB 來產生匯入連結庫。
使用 /DEF 選項執行 LIB 會產生具有 的額外檔案。EXP 擴充功能。 這。EXP 檔案必須稍後用來建置可執行檔。
使用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 的匯入連結庫。
連結兩個 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