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.