Udostępnij za pośrednictwem


Importowanie wywołań funkcji przy użyciu polecenia __declspec(dllimport)

Dodawanie adnotacji do wywołań za pomocą elementu __declspec(dllimport) może przyspieszyć ich działanie. __declspec(dllimport) jest zawsze wymagany do uzyskania dostępu do wyeksportowanych danych DLL.

Importowanie funkcji z biblioteki DLL

Poniższy przykład kodu przedstawia sposób importowania __declspec(dllimport) wywołań funkcji z biblioteki DLL do aplikacji. Załóżmy, że func1 jest to funkcja, która znajduje się w bibliotece DLL niezależnie od pliku wykonywalnego zawierającego funkcję main .

Bez __declspec(dllimport)polecenia podanego w tym kodzie:

int main(void)
{
   func1();
}

kompilator generuje kod, który wygląda następująco:

call func1

a konsolidator tłumaczy wywołanie na coś takiego:

call 0x4000000         ; The address of 'func1'.

Jeśli func1 istnieje w innej biblioteki DLL, konsolidator nie może rozpoznać tego adresu bezpośrednio, ponieważ nie ma możliwości poznania, jaki jest adres func1 . W środowiskach 32-bitowych i 64-bitowych konsolidator generuje thunk pod znanym adresem. W środowisku 32-bitowym thunk wygląda następująco:

0x40000000:    jmp DWORD PTR __imp_func1

Oto __imp_func1 adres func1 miejsca w tabeli adresów importu pliku wykonywalnego. Wszystkie te adresy są znane konsolidatorowi. Moduł ładujący musi zaktualizować tylko tabelę adresów importu pliku wykonywalnego w czasie ładowania, aby wszystko działało poprawnie.

Dlatego użycie __declspec(dllimport) jest lepsze: ponieważ konsolidator nie generuje thunk, jeśli nie jest wymagany. Thunks sprawiają, że kod jest większy (w systemach RISC, może to być kilka instrukcji) i może obniżyć wydajność pamięci podręcznej. Jeśli informujesz kompilator, że funkcja znajduje się w bibliotece DLL, może wygenerować wywołanie pośrednie.

Teraz ten kod:

__declspec(dllimport) void func1(void);
int main(void)
{
   func1();
}

generuje następującą instrukcję:

call DWORD PTR __imp_func1

Nie ma tunk i nie ma jmp instrukcji, więc kod jest mniejszy i szybszy. Możesz również uzyskać ten sam efekt bez __declspec(dllimport) użycia całej optymalizacji programu. Aby uzyskać więcej informacji, zobacz /GL (Optymalizacja całego programu).

W przypadku wywołań funkcji w bibliotece DLL nie chcesz używać wywołania pośredniego. Konsolidator zna już adres funkcji. Ładowanie i przechowywanie adresu funkcji przed wywołaniem pośrednim zajmuje trochę czasu i miejsca. Bezpośrednie wywołanie jest zawsze szybsze i mniejsze. Chcesz użyć __declspec(dllimport) tylko podczas wywoływania funkcji DLL spoza samej biblioteki DLL. Nie używaj __declspec(dllimport) funkcji wewnątrz biblioteki DLL podczas kompilowania tej biblioteki DLL.

Zobacz też

Importowanie do aplikacji