动态链接库隐式加载 dll lib(函数导出符号) .h 导入符号。 在编译的时候被lib加载到EXE中,在程序执行时候将DLL加入内存映射到进程中,用dumpbin查看imports可以看到DLL
显示定义 dll loadlibrary 程序运行时候不会被加载,等到某一特定情况才加载,imports中没有该DLL
需要使用工具dumpbin 查看库导出函数符号名字,导入库名字
注意问题
1 函数导出名字 C++/C extern"C" 不支持重载故而(但是不支持类的导出),函数名不会替换不会乱。避免这种问题可以自己定义模块文件def,可以代替 Extern “C" _declspec(dlexport)
2 函数导出约定 默认stdcall 为帕斯卡调用 CALLBACK 和C _cdecl 语言的默认调用 不相同,体现在参数,函数栈返回值处理不同。
3 DEF定义 当我们在使用不同语言交互时候函数调用规则不同,不能使用extern”C" 但函数导出名称发生了变化,这个时候我们一般通过DEF自己定义函数名 DEF只是为了解决函数名不同编译器的变化问题,同时也具有是的DLL导出功能,但没有指定调用函数约定
_declspec(dllexport) myfuc
LIBRARY "dll名字不需要dll后缀"
EXPORTS
myfunc这样函数名字就不会变化了。
Myfunc = myfunc @NNNN数字序列
如果显示调用DLL LoadLibray LoadProcAddress(HANDLE,MAKEINTRESOURCE(NNNN)/myfunc/Myfunc);
如果是隐式调用需要,lib 需要.h文件这个时候可以这样定义
#ifdef dll_export
#define dll_api _declspec(dllexport)
else
#define dll_api _declspec(dllimport)
#endif
当我们在开发一个底层DLL包,给别人做2次开发的时候,我们一般会提供.lib .h .dll
用下面的宏可以将DLL声明.h和使用DLL头文件合一 这样可以减少我们书写函数声明。
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
在实现dll中我们
#define DLL_EXPORTS
#include<.h>
首先最大区别,静态链接库是在调用模块的程序编译连接过程中,将lib加入到程序中的。没连接一次加载一次内存中多分拷贝。
1 制作lib库函数 因为是连接加载所以 lib X.h都是必须的。 而且默认都要在源文件目录下。 注意lib是不需要DLLMain函数的。他是dll函数入口。
lib制作注意 使用extern "C" 要不函数名字不一样 extern "C" 意思是用C标准调用, C++ 支持重载在编译时候会改变函数名字
我们可以选择MS VC _declspec(dllexport)也可以使用 def(非微软标准)def作用是用另一种规范代替 _declspec(dllexport)
DllMain(__in HANDLE _HDllHandle, __in DWORD _Reason, __in_opt LPVOID _Reserved)
HDllHandle 是dll模块在内存中的句柄,但是被映射到每个进程中,因而句柄数值是不同的。
DLL 我们经常看见2次开发库,会提供dll lib .h三个文件。 我们在设立简单介绍下。 当我们用静态连接,我们可以不需要extern"C"
dll 其实只需要这一个便可以访问,这个是现实访问。 调用LoadLibrary GetProcAddress函数
lib 其实只是dll函数导出符号 #pragma comment(lib,"out.lib")
.h 其实是我们重新声明了函数如 _declspec(dllimport)Function
这样隐士定义了便不需要加载,找地址。 编译成功不一定,运行成功
用下面的宏可以将DLL声明.h和使用DLL头文件合一 这样可以减少我们书写函数声明。
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
在实现dll中我们
#define DLL_EXPORTS
#include<.h>