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调用。 LoadLibrary():载入指定的动态链接库,并将它映射到当前进程使用的地址空间 GetProcAdress:检索指定的动态链接库(DLL)中的输出函数地址 FARPROC WINAPI GetProcAddress(__in HMODULE hModule, __in LPCSTR LpProcName); 应该知道你要的函数的类型是什么,可以用typedef的方法定义函数类型,然后定义一个这种类型的变量,你得到地址后,将地址的类型转换并存到那个变量中就行了 HMODULE hModule=GetModuleHandle("kernel32.dll"); if (hModule)
|
_declspec是一种扩展属性的定义 _declspec(dllimport) 是说这个函数是从别的DLL导入。我要用。 不使用__declspec(dllimport)也能正确编译代码
|
.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
全局变量的导入及使用 方法 在其他dll或者exe中,导入该变量: 一种方法是extern int dllinum ;但该声明所 入的并不是DLL中全局变量本身,而是其地址 ,应用程序必须通过强制指针转换来使用DLL中的全局变量,要使用 *(int *)dllinum 来使用该变量,如 *(int *)dllinum = 1; 第二种方法用_declspec(dllimport)导入 extern int _declspec(dllimport) dllinum ; 如 dllinum = 1;
|
windows dll 学习
最新推荐文章于 2024-07-04 23:08:22 发布