VS2005 ->Win32->DLL.
1.生成DLL
添加.h文件,
#include "stdafx.h"
__declspec(dllexport) void Test();
//也可以直接使用extern "C" void Test()的方式
.CPP文件
void Test()
{
::MessageBoxA(NULL,"Test","Test",NULL);
}
.def文件
LIBRARY "ServerDll"
EXPORTS
Test @ 1
2测试DLL
简单的MFC对话框程序,添加单机按钮消息。
名词解释:
_declspec(thread)可以降低程序员的负担,又能做到线程局部存储的要求。VC++允许一个变量或结构被声明为“具有线程局部性”。例如,下面的声明,如果放在一个DLL之中,将产生出一个全局变量,对每一个进程而言独一无二:
DWORD gProgressCounter;
但是如果这样声明,它就是对每一个线程独一无二:
_declspec(thread) DWORD gProgressCounter;
每一个以这种方式声明对象的EXE和DLL,将在可执行文件中有一个特殊的节区(section),内含所有的线程局部变量。当EXE或DLL被载入时,操作系统会认识这个节区并适当的处理之。这个节区会被操作系统社定为“对每一个线程具有局部性”。
当一个EXE被载入时,操作系统扫描可执行文件以及所有静态链接(implicity linked)的DLLs,以便找出所有的线程局部节区。所有节区的大小被加总在一起以求出每个线程启动时应该配置的内存数量。
declspec(dllimport) 是说这个函数是从别的DLL导入。我要用。
_declspec(dllexport) 是说这个函数要从本DLL导出。我要给别人用。
//下面摘自http://support.microsoft.com/kb/132044/zh-cn
为函数调用中使用 _declspec(dllimport)
<script type="text/javascript"></script> 在下面的代码示例假定 func1 是驻留在单独从.exe 文件包含 main () 函数的 DLL 中的函数。
_declspec(dllimport),而不给出此代码:
void main(void) {
func1();
}
编译器生成类似下面的代码:
call func1
和链接器将翻译成如下所示调用:
call 0x4000000 ; The address of 'func1'.
'func1' 存在于另一个 DLL 中,如果链接器不能解决此直接因为它无法知道 'func1 的地址什么。 在 16 位环境中链接器将此代码地址添加到列表中加载程序在运行时用正确的地址修补该.exe。 在 32 位环境中链接器生成一个 thunk,它不会知道地址。 在 thunk 如下所示:
0x40000000: jmp DWORD P TR __imp_func1
__imp_func1 以下是为 func1 的插槽中导入地址表.exe 文件的地址。 链接器因此已知的所有地址。 若要更新在加载时,一切就会正常工作的.exe 文件导入地址表仅有加载程序。
因此,使用 _declspec(dllimport) 是更好的因为它是更好的如果链接器不生成一个 thunk,如果没有到。 thunk 使代码更大 (要 RISC 系统上它可以是几个说明) 并会降低缓存性能。 如果通知编译器函数是 DLL 中,它可以为您生成间接调用。
因此,现在此代码:
__declspec(dllimport) void func1(void);
void main(void) {
func1();
}
生成此指令:
call DWORD PTR __imp_func1
不存在任何 thunk 并没有 jmp 指令使代码是更小、 更快。
手动,对于 DLL 内部的函数调用,您不希望不必使用间接调用。 您已经知道函数的地址。 时间和空间所需加载和存储之前间接调用函数的地址,因此直接调用总是更快和更小。 要从外部调用 DLL 函数时使用 __declspec(dllimport) DLL 本身。 不要使用上一个 DLL 内部的函数的 __declspec(dllimport),构建该 DLL 时。