使用 匯入函式呼叫 __declspec(dllimport)
使用 __declspec(dllimport)
標註呼叫可以加快呼叫速度。 __declspec(dllimport)
一律需要存取導出的 DLL 數據。
從 DLL 匯入函式
下列程式代碼範例示範如何使用 將 __declspec(dllimport)
DLL 的函式呼叫匯入應用程式。 func1
假設 是 DLL 中的函式,與包含main函式的可執行檔不同。
如果沒有 __declspec(dllimport)
,請指定下列程式代碼:
int main(void)
{
func1();
}
編譯程式會產生如下所示的程序代碼:
call func1
而連結器會將呼叫轉譯成類似以下的內容:
call 0x4000000 ; The address of 'func1'.
如果 func1
存在於另一個 DLL 中,則連結器無法直接解析此地址,因為它無法知道的地址 func1
為何。 在 32 位和 64 位環境中,連結器會在已知的地址產生 Thunk。 在 32 位的環境中,Thunk 看起來像:
0x40000000: jmp DWORD PTR __imp_func1
以下是 __imp_func1
可執行文件匯入位址表中位置的位址 func1
。 連結器知道所有這些位址。 載入器只需要在載入時更新可執行文件的匯入地址數據表,才能正常運作。
這就是為什麼使用 __declspec(dllimport)
更好:因為連結器在不需要時不會產生 Thunk。 Thunks 會使程式代碼變大(在 RISC 系統上,它可以是數個指示),而且可能會降低快取效能。 如果您告訴編譯程式函式位於 DLL 中,它可以為您產生間接呼叫。
因此,現在此程式代碼:
__declspec(dllimport) void func1(void);
int main(void)
{
func1();
}
會產生此指示:
call DWORD PTR __imp_func1
沒有 Thunk,也沒有 jmp
指示,因此程式代碼會更小、更快。 您也可以使用整個程式優化來 __declspec(dllimport)
取得相同的效果。 如需詳細資訊,請參閱 /GL (整個程式最佳化)。
針對 DLL 內的函數調用,您不需要使用間接呼叫。 鏈接器已經知道函式的位址。 在間接呼叫之前,載入和儲存函式的位址需要額外的時間和空間。 直接呼叫一律會更快且更小。 您只想要在從 DLL 本身外部呼叫 DLL 函式時使用 __declspec(dllimport)
。 建置該 DLL 時,請勿 __declspec(dllimport)
在 DLL 內的函式上使用 。