目录
xxx.lib -- 引入库文件,保存的是xxx.dll中导出的函数和变量的符号名
extern与__declspec(dllimport)区别
推荐工具 Dependency Walker 2.2:查看一个可执行程序所依赖的动态链接库,
1. 隐式链接
xxx.lib -- 引入库文件,保存的是xxx.dll中导出的函数和变量的符号名
不会包含实际代码,为链接程序提供必要的信息,以便在可执行文件中建立 动态链接时需要用到的 重定位表
只是提供一种映射关系
VS2013中是在这个位置添加:
xxx.dll -- 导出的动态链接库
需要放置在这些位置下才可以被程序找到
四大路径及顺序
1. 程序的执行路径
2. 当前路径(.)【一个点代表当前路径,两个点代表上层路径】
3. 系统路径
例如C:\Windows\System,C:\Windows\System32,C:\Windows\SysWOW64
4. 系统环境变量(PATH)中所列出的路径
举例说明:调用OpenCV的dll时一般放置在程序的执行路径(1),或者把它添加到系统环境变量(PATH)中(4)。
参考博客
extern与__declspec(dllimport)区别
__declspec(dllimport)会告诉编译器该函数是从动态链接库引入的,编译器可以生成运行效率更高的代码。
如果调用的函数来自于动态链接库,应该采用这种方式声明外部函数。
推荐工具 Dependency Walker 2.2:查看一个可执行程序所依赖的动态链接库,
下载地址与更多信息可参考 http://www.dependencywalker.com/
2. 显式加载(动态加载)
相关函数
HMODULE WINAPI LoadLibrary(
_In_ LPCTSTR lpFileName
);
FARPROC GetProcAddress(
HMODULE hModule,
LPCWSTR lpProcName
);
BOOL FreeLibrary(
HMODULE hLibModule
);
【注意】每调用一次 LoadLibrary 函数就应调用一次 FreeLibrary 函数,以保证不会有多余的库模块在应用程序结束后仍留在内存中,否则导致内存泄漏。
参考阅读
示例代码
HINSTANCE hInst;
hInst = LoadLibrary("MyDll2.dll"); //显式加载(动态加载)dll
typedef int (*ADDPROC) (int a, int b); //定义函数指针类型
ADDPROC Add = (ADDPROC)GetProcAddress(hInst, "add"); //获取dll的导出函数
if(!Add){
MessageBox("获取函数地址失败!");
return;
}
FreeLibrary(hInst);
也可以参考如下博客
Windows API封装:LoadLibrary/FreeLibrary
3.隐式链接与显式加载对比
隐式链接 | 显式加载 | |
需要的文件 | .lib/.dll/.h | .dll |
何时被加载至内存中 | 程序启动时 | 需要时才加载 |
同时加载多个dll时的资源浪费情况 | 严重 | 一般 |
使用方便程度 | 非常 | 一般 |
使用dumpbin -imports查看调用者 | 有信息 | 无信息 |
特别说明 | 本质上,隐式链接是在程序启动时通过LoadLibrary方式加载dll |
【注意】不管哪种方式,dll都需要被调用者找到才可以,参考上面的“四大路径及顺序”。
更多内容请看C/C++动态链接库(DLL)详解
来源:孙鑫_VC++_学习笔记