Importing function calls using __declspec(dllimport)

Annotating calls by using the __declspec(dllimport) can make them faster. __declspec(dllimport) is always required to access exported DLL data.

Import a function from a DLL

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's in a DLL separate from the executable file that contains the main function.

Without __declspec(dllimport), given this code:

int main(void)
{
   func1();
}

the compiler generates code that looks like this:

call func1

and the linker translates the call into something like this:

call 0x4000000         ; The address of 'func1'.

If func1 exists in another DLL, the linker can't resolve this address directly because it has no way of knowing what the address of func1 is. In 32-bit and 64-bit environments, the linker generates a thunk at a known address. In a 32-bit environment the thunk looks like:

0x40000000:    jmp DWORD PTR __imp_func1

Here __imp_func1 is the address for the func1 slot in the import address table of the executable file. All these addresses are known to the linker. The loader only has to update the executable file's import address table at load time for everything to work correctly.

That's why using __declspec(dllimport) is better: because the linker doesn't generate a thunk if it's 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:

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

generates this instruction:

call DWORD PTR __imp_func1

There's no thunk and no jmp instruction, so the code is smaller and faster. You can also get the same effect without __declspec(dllimport) by using whole program optimization. For more information, see /GL (Whole Program Optimization).

For function calls within a DLL, you don't want to have to use an indirect call. The linker already knows the function's address. It takes extra time and space 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. Don't use __declspec(dllimport) on functions inside a DLL when building that DLL.

See also

Importing into an Application