windows dll 学习

dll目的是软件共享和重用

 

注意:

1.dll函数创建的任何对象都为调用线程或进程所拥有,dll绝对不会拥有任何对象。

 

构建dll

编译器把源文件生成obj文件,链接器把obj文件合成,生成dll文件(包含二进制代码和全局/静态变量)。如果有导出函数,还生成lib文件(只列出函数和变量的符号名)。

 

构建exe

编译器把源文件生成obj文件,链接器把obj文件合成,并使用lib文件,解析导出函数或变量的引用,生成可执行文件exe(保护可执行文件的二进制代码和全局静态变量,还有一个导入段(列出每个dll名称、函数和变量的符号名))。

 

运行可执行程序

1.进程创建虚拟地址空间

2.把可执行程序映射到进程的地址空间

3.检查可执行程序的导入段

4.把所有的dll映射到进程的地址空间。

 

 

extern C 告诉编译器不要对变量名或函数名进行改编。混用c和c++编程,要用extern C

 

_stdcall 等价于 winapi 调用约束,会改编函数名。

为了不改编函数名,使用.def文件,添加 EXPORTS段

 

lib是编译时用到的,dll是运行时用到的。
lib记录了dll中函数的入口和位置,dll中是函数的具体内容;应用程序使用LIB文件链接到DLL文件

隐性调用:编译程序时需要头文件、lib文件,运行时需要DLL文件,并且运行过程中DLL文件一直被占用。 一般使用隐性调用,在属性->linker->input->additional dependencies 添加.lib 文件

 

显性调用:编译时什么都不需要,在需要使用DLL中的函数时,通过LoadLibrary()和GetProcAdress()这两个API调用。
只需要一个DLL文件即可,而且在需要使用的时候DLL才被占用,使用完毕即解除占用(FreeLibrary)。

LoadLibrary():载入指定的动态链接库,并将它映射到当前进程使用的地址空间

GetProcAdress:检索指定的动态链接库(DLL)中的输出函数地址

FARPROC WINAPI GetProcAddress(__in HMODULE hModule, __in LPCSTR LpProcName);

应该知道你要的函数的类型是什么,可以用typedef的方法定义函数类型,然后定义一个这种类型的变量,你得到地址后,将地址的类型转换并存到那个变量中就行了

HMODULE hModule=GetModuleHandle("kernel32.dll");

if (hModule)
  {
  typedef DWORD (CALLBACK *LPFNREGISTER)(DWORD,DWORD);
  LPFNREGISTER lpfnRegister;
  lpfnRegister=(LPFNREGISTER)GetProcAddress(hModule,"RegisterServiceProcess");
  if (lpfnRegister)
  {
  (*lpfnRegister)(NULL,1L);
  }
  }

 

_declspec是一种扩展属性的定义                                                                                                          _declspec(dllimport)   是说这个函数是从别的DLL导入。我要用。      不使用__declspec(dllimport)也能正确编译代码                 
_declspec(dllexport)   是说这个函数要从本DLL导出。我要给别人用。  等价于DLL需要提供.def文件  两者互斥,只能2选1。 def文件只能用来导出函数,不能用于导出整个类。导出C++类,必须用__declspec(dllexport)   其替代宏AFX_EXT_CLASS

 

 

.def  文件格式
; 项目名.def : 声明 DLL 的模块参数。 分号;后的文本内容行为注释
LIBRARY      "项目名"
EXPORTS
函数名1 @1
函数名2 @2
……
函数名n @n                                                                                                                           ;

如果希望用MFC(C++)编写的规则DLL中的函数,也能够被非MFC程序来调用,需要为函数声明指定extern "C"  如 extern "C" __declspec(dllexport)

 

默认情况下VC使用的是__cdecl的函数调用方式,如果产生的dll只会给C/C++程序使用,那么就没必要定义为__stdcall调用方式

 

判断dll是否映射到进程的地址空间的函数:getmodulehandle,如果传入参数为null ,则返回的是当前可执行程序的句柄。

获取正在运行的可执行文件的路径的函数:getmodulefilename。

 

导出变量

DLL中导出全局变量的方法

1. 第一种是用__declspec(dllexport)进行导出声明 如 extern __declspec(dllexport) int  dllinum;

2.第二种用模块定义文件(.def)

EXPORTS
        dllinum DATA 

 

全局变量的导入使用 方法

在其他dll或者exe中,导入该变量:

一种方法是extern int dllinum ;但该声明所 入的并不是DLL中全局变量本身,而是其地址 ,应用程序必须通过强制指针转换来使用DLL中的全局变量,要使用 *(int *)dllinum 来使用该变量,如 *(int *)dllinum = 1;

第二种方法用_declspec(dllimport)导入

extern int _declspec(dllimport) dllinum ;  如 dllinum  = 1;

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值