You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/build/importing-function-calls-using-declspec-dllimport.md
+21-16Lines changed: 21 additions & 16 deletions
Original file line number
Diff line number
Diff line change
@@ -1,16 +1,21 @@
1
1
---
2
-
title: "Importing Function Calls Using __declspec(dllimport)"
3
-
ms.date: "11/04/2016"
2
+
title: "Importing function calls using __declspec(dllimport)"
3
+
description: "How and why to use __declspec(dllimport) when calling DLL data and functions."
4
+
ms.date: "05/03/2020"
4
5
helpviewer_keywords: ["importing function calls [C++]", "dllimport attribute [C++], function call imports", "__declspec(dllimport) keyword [C++]", "function calls [C++], importing"]
5
6
ms.assetid: 6b53c616-0c6d-419a-8e2a-d2fff20510b3
6
7
---
7
-
# Importing Function Calls Using __declspec(dllimport)
8
+
# Importing function calls using `__declspec(dllimport)`
8
9
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
+
Annotating calls by using the **`__declspec(dllimport)`**can make them faster. **`__declspec(dllimport)`** is always required to access exported DLL data.
10
11
11
-
Without **__declspec(dllimport)**, given this code:
12
+
## Import a function from a DLL
12
13
13
-
```
14
+
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.
15
+
16
+
Without **`__declspec(dllimport)`**, given this code:
17
+
18
+
```C
14
19
intmain(void)
15
20
{
16
21
func1();
@@ -19,29 +24,29 @@ int main(void)
19
24
20
25
the compiler generates code that looks like this:
21
26
22
-
```
27
+
```asm
23
28
call func1
24
29
```
25
30
26
31
and the linker translates the call into something like this:
27
32
28
-
```
33
+
```asm
29
34
call 0x4000000 ; The address of 'func1'.
30
35
```
31
36
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:
37
+
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:
33
38
34
-
```
39
+
```asm
35
40
0x40000000: jmp DWORD PTR __imp_func1
36
41
```
37
42
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.
43
+
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.
39
44
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.
45
+
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.
41
46
42
47
So now this code:
43
48
44
-
```
49
+
```C
45
50
__declspec(dllimport) void func1(void);
46
51
int main(void)
47
52
{
@@ -51,13 +56,13 @@ int main(void)
51
56
52
57
generates this instruction:
53
58
54
-
```
59
+
```asm
55
60
call DWORD PTR __imp_func1
56
61
```
57
62
58
-
There is no thunk and no `jmp` instruction, so the code is smaller and faster.
63
+
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).
59
64
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.
65
+
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.
0 commit comments