The following code example shows how to use _declspec(dllimport) to import function calls from a DLL into an application. Assume that func1
is a function that resides in a DLL separate from the .exe file that contains the main function.
Without __declspec(dllimport), given this code:
В | Copy Code |
---|---|
int main(void) { func1(); } |
the compiler generates code that looks like this:
В | Copy Code |
---|---|
call func1 |
and the linker translates the call into something like this:
В | Copy Code |
---|---|
call 0x4000000 ; The address of 'func1'. |
If func1
exists in another DLL, the linker cannot resolve this directly because it has no way of knowing what the address of func1
is. In 16-bit environments, the linker adds this code address to a list in the .exe file that the loader would patch at run time with the correct address. In 32-bit environments, the linker generates a thunk of which it does know the address. The thunk looks like:
В | Copy Code |
---|---|
0x40000000: jmp DWORD PTR __imp_func1 |
Here imp_func1
is the address for the func1
slot in the import address table of the .exe file. All the addresses are thus known to the linker. The loader only has to update the .exe file's import address table at load time for everything to work correctly.
Therefore, using __declspec(dllimport) is better because the linker does not generate a thunk if it is not required. Thunks make the code larger (on RISC systems, it can be several instructions) and can degrade your cache performance. If you tell the compiler the function is in a DLL, it can generate an indirect call for you.
So now this code:
В | Copy Code |
---|---|
__declspec(dllimport) void func1(void); int main(void) { func1(); } |
generates this instruction:
В | Copy Code |
---|---|
call DWORD PTR __imp_func1 |
There is no thunk and no jmp
instruction, so the code is smaller and faster.
On the other hand, for function calls inside a DLL, you do not want to have to use an indirect call. You already know a function's address. Because time and space are required to load and store the address of the function before an indirect call, a direct call is always faster and smaller. You only want to use __declspec(dllimport) when calling DLL functions from outside the DLL itself. Do not use __declspec(dllimport) on functions inside a DLL when building that DLL.