Importování volání funkce pomocí __declspec(dllimport)
Následující příklad kódu ukazuje, jak používat _declspec(dllimport) pro importování volání funkce z knihovny DLL do aplikace.Předpokládejme, že func1 je funkce, která se nachází v knihovně DLL oddělené od souboru .exe, který obsahuje funkci main.
Bez __declspec(dllimport), daný tento kód:
int main(void)
{
func1();
}
Kompilátor vygeneruje kód, který vypadá takto:
call func1
a propojovací program převede volání přibližně do této podoby:
call 0x4000000 ; The address of 'func1'.
Pokud func1 existuje v jiné knihovně DLL, propojovací program toto nemůže přímo rozlišit, protože nemá žádný způsob jak vědět, jaká je adresa func1.V 16bitových prostředích propojovací program přidá adresu tohoto kódu do seznamu v souboru .exe, který by zavaděč za běhu aktualizoval správnou adresou.Ve 32bitových a 64bitových prostředích propojovací program vygeneruje volání kódu s jinou bitovou šířkou, u kterého zná jeho adresu.Ve 32bitovém prostředí toto volání kódu s jinou bitovou šířkou vypadá takto:
0x40000000: jmp DWORD PTR __imp_func1
Zde je imp_func1 adresa pro slot func1 v tabulce importovaných adres souboru .exe.Všechny adresy jsou tedy známy propojovacímu programu.Zavaděč pouze musí aktualizovat tabulku importovaných adres souboru .exe při načítání, aby vše pracovalo správně.
Proto je použití __declspec(dllimport) výhodnější, protože propojovací program negeneruje volání kódu s jinou bitovou šířkou, není-li to požadováno.Volání kódu s jinou bitovou šířkou kód zvětšuje (v systémech RISC to může být několik instrukcí) a může snížit výkon mezipaměti.Pokud řeknete kompilátoru, že je funkce v knihovně DLL, může za vás vygenerovat nepřímé volání.
Proto nyní tento kód:
__declspec(dllimport) void func1(void);
int main(void)
{
func1();
}
vygeneruje tuto instrukci:
call DWORD PTR __imp_func1
Není zde žádné volání kódu s jinou bitovou šířkou a žádná instrukce jmp, takže je kód menší a rychlejší.
Na druhé straně pro volání funkcí uvnitř knihovny DLL nechcete muset používat nepřímé volání.Již znáte adresu funkce.Protože je pro načtení a uložení adresy funkce před nepřímým voláním vyžadován čas a prostor, je přímé volání vždy rychlejší a menší.Chcete použít __declspec(dllimport) jedině při volání funkcí knihovny DLL zvenčí samotné knihovny DLL.Nepoužívejte __declspec(dllimport) na funkcích uvnitř knihovny DLL při vytváření této knihovny DLL.