Partilhar via


Importando chamadas de função usando __declspec(dllimport)

Anotar chamadas usando o __declspec(dllimport) pode torná-las mais rápidas. __declspec(dllimport) é sempre necessário para acessar dados DLL exportados.

Importar uma função de uma DLL

O exemplo de código a seguir mostra como usar __declspec(dllimport) para importar chamadas de função de uma DLL para um aplicativo. Suponha que func1 é uma função que está em uma DLL separada do arquivo executável que contém a função principal .

Sem __declspec(dllimport), dado este código:

int main(void)
{
   func1();
}

O compilador gera código com esta aparência:

call func1

e o linker traduz a chamada em algo assim:

call 0x4000000         ; The address of 'func1'.

Se func1 existir em outra DLL, o vinculador não pode resolver esse endereço diretamente porque não tem como saber qual é o endereço func1 . Em ambientes de 32 bits e 64 bits, o vinculador gera um thunk num endereço conhecido. Em um ambiente de 32 bits, o "thunk" se parece com:

0x40000000:    jmp DWORD PTR __imp_func1

Aqui __imp_func1 está o endereço do slot func1 na tabela de endereços de importação do ficheiro executável. Todos esses endereços são conhecidos pelo vinculador. O carregador só precisa atualizar a tabela de endereços de importação do arquivo executável no momento do carregamento para que tudo funcione corretamente.

É por isso que usar __declspec(dllimport) é melhor: porque o linker não gera um thunk se não for necessário. Thunks tornam o código maior (em sistemas RISC, pode ser várias instruções) e podem degradar o desempenho do cache. Se você informar ao compilador que a função está em uma DLL, ele pode gerar uma chamada indireta para você.

Então agora este código:

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

gera esta instrução:

call DWORD PTR __imp_func1

Não há thunk nem jmp instrução, então o código é menor e mais rápido. Você também pode obter o mesmo efeito ao usar a otimização de todo o programa sem __declspec(dllimport). Para obter mais informações, consulte /GL (Otimização de todo o programa).

Para chamadas de função dentro de uma DLL, você não quer ter que usar uma chamada indireta. O vinculador já sabe o endereço da função. Leva tempo e espaço extra para carregar e armazenar o endereço da função antes de uma chamada indireta. Uma chamada direta é sempre mais rápida e menor. Você só deseja usar __declspec(dllimport) ao chamar funções DLL de fora da própria DLL. Não use __declspec(dllimport) em funções dentro de uma DLL ao criar essa DLL.

Ver também

Importando para um aplicativo