Skip to content

Commit dbb3696

Browse files
author
Colin Robertson
committed
Fix #2029
1 parent a00cb31 commit dbb3696

File tree

1 file changed

+16
-15
lines changed

1 file changed

+16
-15
lines changed

docs/build/importing-function-calls-using-declspec-dllimport.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
---
22
title: "Importing Function Calls Using __declspec(dllimport)"
3-
ms.date: "11/04/2016"
3+
description: "How and why to use __declspec(dllimport) when calling DLL data and functions."
4+
ms.date: "05/03/2020"
45
helpviewer_keywords: ["importing function calls [C++]", "dllimport attribute [C++], function call imports", "__declspec(dllimport) keyword [C++]", "function calls [C++], importing"]
56
ms.assetid: 6b53c616-0c6d-419a-8e2a-d2fff20510b3
67
---
7-
# Importing Function Calls Using __declspec(dllimport)
8+
# Importing Function Calls Using `__declspec(dllimport)`
89

9-
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.
10+
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.
1011

11-
Without **__declspec(dllimport)**, given this code:
12+
Without **`__declspec(dllimport)`**, given this code:
1213

13-
```
14+
```C
1415
int main(void)
1516
{
1617
func1();
@@ -19,29 +20,29 @@ int main(void)
1920
2021
the compiler generates code that looks like this:
2122
22-
```
23+
```asm
2324
call func1
2425
```
2526

2627
and the linker translates the call into something like this:
2728

28-
```
29+
```asm
2930
call 0x4000000 ; The address of 'func1'.
3031
```
3132

32-
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 and 64-bit environments, the linker generates a thunk of which it does know the address. In a 32-bit environment the thunk looks like:
33+
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:
3334

34-
```
35+
```asm
3536
0x40000000: jmp DWORD PTR __imp_func1
3637
```
3738

38-
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.
39+
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.
3940

40-
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.
41+
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.
4142

4243
So now this code:
4344

44-
```
45+
```C
4546
__declspec(dllimport) void func1(void);
4647
int main(void)
4748
{
@@ -51,13 +52,13 @@ int main(void)
5152
5253
generates this instruction:
5354
54-
```
55+
```asm
5556
call DWORD PTR __imp_func1
5657
```
5758

58-
There is no thunk and no `jmp` instruction, so the code is smaller and faster.
59+
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)](reference/gl-whole-program-optimization.md).
5960

60-
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.
61+
For function calls within a DLL, you don't want to have to use an indirect call. You already know 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.
6162

6263
## See also
6364

0 commit comments

Comments
 (0)