Sdílet prostřednictvím


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.

Viz také

Koncepty

Import do aplikace