Partilhar via


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

A anotação de chamadas usando __declspec(dllimport) poderá torná-las mais rápidas. __declspec(dllimport) sempre é necessário para acessar dados de DLL exportadas.

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 seja uma função que está em uma DLL separada do arquivo executável que contém a função main.

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

int main(void)
{
   func1();
}

o compilador gera um código semelhante a este:

call func1

e o vinculador converte a chamada em algo assim:

call 0x4000000         ; The address of 'func1'.

Se func1 estiver em outra DLL, o vinculador não poderá resolver esse endereço diretamente porque não terá como saber qual é o endereço de func1. Em ambientes de 32 bits e 64 bits, o vinculador gera uma conversão em um endereço conhecido. Em um ambiente de 32 bits, a conversão é semelhante a:

0x40000000:    jmp DWORD PTR __imp_func1

Aqui, __imp_func1 é o endereço do slot func1 na tabela de endereços de importação do arquivo 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 tempo de carregamento para que tudo funcione corretamente.

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

Portanto, 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á nenhuma conversão nem instrução jmp, portanto, o código fica menor e mais rápido. Você também pode obter o mesmo efeito sem __declspec(dllimport) ao usar a otimização de programa inteira. Para obter mais informações, consulte /GL (otimização de programa inteiro).

Para chamadas de função dentro de uma DLL, você não deseja usar uma chamada indireta. O vinculador já sabe o endereço da função. São necessários tempo e espaço adicionais 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 de DLL fora da própria DLL. Não use __declspec(dllimport) em funções dentro de uma DLL ao criar essa DLL.

Confira também

Importando para um aplicativo