使用 __declspec(dllimport) 能够优化对DLL导出函数的调用.
> 不使用时:
[DLL]
#ifdef THEDLL_EXPORTS
#define THEDLL_API __declspec(dllexport)
#else
#define THEDLL_API __declspec(dllimport)
#endif
// THEDLL_API
int fntheDll(void);
[EXE]
#include "..\\theDll\\theDll.h"
#pragma comment(lib, "..\\Release\\theDll.lib")
#include <Windows.h>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
cout << fntheDll() << endl;
return 0;
}
问题是: 链接器生成不必要的 thunk:
cout << fntheDll() << endl;
00BC1000 A1 3C 20 BC 00 mov eax,dword ptr [__imp_std::endl (0BC203Ch)]
00BC1005 50 push eax
00BC1006 E8 13 08 00 00 call fntheDll (0BC181Eh)
^
// 链接器生成的 thunk |
fntheDll: |
|----------------------------------------------/
v
00BC181E FF 25 B8 20 BC 00 jmp dword ptr [__imp_fntheDll (0BC20B8h)]
|
|
\--------> EXE IAT(导入表)中的地址, 即, 函数 fntheDll() 在EXE地址空间的位置.
>使用时:
[DLL]
#ifdef THEDLL_EXPORTS
#define THEDLL_API __declspec(dllexport)
#else
#define THEDLL_API __declspec(dllimport)
#endif
THEDLL_API int fntheDll(void);
[EXE]
#include "..\\theDll\\theDll.h"
#pragma comment(lib, "..\\Release\\theDll.lib")
#include <Windows.h>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
cout << fntheDll() << endl;
return 0;
}
链接器没有生成 thunk:
cout << fntheDll() << endl;
00E11000 A1 3C 20 E1 00 mov eax,dword ptr [__imp_std::endl (0E1203Ch)]
00E11005 50 push eax
00E11006 FF 15 B8 20 E1 00 call dword ptr [__imp_fntheDll (0E120B8h)]
|
|
\--------> EXE IAT(导入表)中的地址, 即, 函数 fntheDll() 在EXE地址空间的位置.
结论: 所以通过 __declspec(dllimport) 指示导入函数, 链接器不会生成不必要的中间thunk, 而该thunk使生成的EXE更大, 执行时多了一次跳转。
> 不使用时:
[DLL]
#ifdef THEDLL_EXPORTS
#define THEDLL_API __declspec(dllexport)
#else
#define THEDLL_API __declspec(dllimport)
#endif
// THEDLL_API
int fntheDll(void);
[EXE]
#include "..\\theDll\\theDll.h"
#pragma comment(lib, "..\\Release\\theDll.lib")
#include <Windows.h>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
cout << fntheDll() << endl;
return 0;
}
问题是: 链接器生成不必要的 thunk:
cout << fntheDll() << endl;
00BC1000 A1 3C 20 BC 00 mov eax,dword ptr [__imp_std::endl (0BC203Ch)]
00BC1005 50 push eax
00BC1006 E8 13 08 00 00 call fntheDll (0BC181Eh)
^
// 链接器生成的 thunk |
fntheDll: |
|----------------------------------------------/
v
00BC181E FF 25 B8 20 BC 00 jmp dword ptr [__imp_fntheDll (0BC20B8h)]
|
|
\--------> EXE IAT(导入表)中的地址, 即, 函数 fntheDll() 在EXE地址空间的位置.
>使用时:
[DLL]
#ifdef THEDLL_EXPORTS
#define THEDLL_API __declspec(dllexport)
#else
#define THEDLL_API __declspec(dllimport)
#endif
THEDLL_API int fntheDll(void);
[EXE]
#include "..\\theDll\\theDll.h"
#pragma comment(lib, "..\\Release\\theDll.lib")
#include <Windows.h>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
cout << fntheDll() << endl;
return 0;
}
链接器没有生成 thunk:
cout << fntheDll() << endl;
00E11000 A1 3C 20 E1 00 mov eax,dword ptr [__imp_std::endl (0E1203Ch)]
00E11005 50 push eax
00E11006 FF 15 B8 20 E1 00 call dword ptr [__imp_fntheDll (0E120B8h)]
|
|
\--------> EXE IAT(导入表)中的地址, 即, 函数 fntheDll() 在EXE地址空间的位置.
结论: 所以通过 __declspec(dllimport) 指示导入函数, 链接器不会生成不必要的中间thunk, 而该thunk使生成的EXE更大, 执行时多了一次跳转。