dll文件指定 /DLL开关 /ENTRY指定进入函数
加载dll的两种方法:
隐式:最常用 在link中指定相应dll的lib文件,
显式:LoadLibrary/Ex来显式的加载dll文件
dll中的函数被加载后,能被进程中的线程使用
dll的函数如何得到参数:使用加载dll的进程中的线程的栈,也使用线程栈来分配需要的局部变量
dll中的代码创建的任何对象都归调用的线程或进程,因为dll没有自己的局部堆
dll的进入退出函数
进入函数:当系统在加载dll时用来通知我的dll文件现在该干什么了。注意:dll是由系统加载的,在加载时
,如果想要做什么,就必须由系统通知你,然后你根据通知再来决定做什么,不可能在系统加载时,由你决定
一般作的是进/线程的初始化
BOOL WINAPI DllMain(HINSTANCE hinstDll,DWORD fdwReason,LPVOID fImpLoad)
hinstDll表示dll文件被映射到虚拟地址空间中的内存地址
fdwReason指出DllMain函数(dll文件)因什么原因被调用,是进程创建了,还是线程创建了等等
DLL_PROCESS_ATTACH
dll首次被加载时,系统调用DllMain并传进DLL_PROCESS_ATTACH,也就是当新的进程需要某个dll时,系统以
DLL_PROCESS_ATTACH的原因来调用dll文件的
DLL_PROCESS_DETACH
表示系统将dll从进程空间中解除
DLL_THREAD_ATTACH
在进程中创建线程时,系统察看进程中所有dll并以DLL_THREAD_ATTACH原因来调用DllMain函数
DLL_THREAD_DETACH
当线程结束时 系统调用DllMain
从dll中输出函数和变量
__declspec(dllexport)
dll的头文件
包含输出函数和变量
//dll.h
#ifndef MYLIBAPI
#define MYLIBAPI __declspec(dllimport)
#endif
MYLIBAPI int Add(int nLeft,int nRight)
//dll.c
#define MYLIBAPI __declspec(dllexport)
#include "dll.h"
int Add(int nLeft,int nRight)
{
return(nLeft+nRight);
}
//在编译时定义MYLIBAPI __declspec(dllexport)
符合预编译的表面意思,所以在.c中而不在.h中,其实也可以在.h中
在exe或dll映射之间共享数据
通常exe中的全局变量不是可以共享的,但是有时也要共享
#pragma data_seg("segname")
例如
设置编译器
#pragma data_seg("Shared")
long g_lModuleUsage=0;//不出始化不会被放入Shared节中的
#pragma data_seg()
还要设置连接器
告诉它这节中的变量要被共享的
/SECTION:name,attributes
/SECTION:Shared,RWS
开关必须大写
也可以
#pragma comment(linker,"/SECTION:Shared,RWS")
使用上面的技术可以让程序只运行一个实例
代码详见Windows高级编程指南
12章