dll和lib浅析
1. 概念
lib:静态库,会编译链接到目标文件。
dll:动态链接库,不会编译进目标文件,在运行目标文件时需要。
2.生成与使用
①静态库
生成方式:
add_library(static_lib
STATIC
${SRC_FILES})
使用方法:
target_link_libraries(obj static_lib),其中obj为目标文件,使用方法简单,唯一缺陷是目标文件会比较大。
②动态库
add_library(shared_dll
SHARED
${SRC_FILES})
上述方法只是生成了一个shared_dll.dll,但还无法被第三方使用,会报找不shared_dll.lib,因此要做到被第三方使用还需做以下工作:
这里以导出类dll为例讲解,如下导出Message类dll:
#pragma once
#ifdef FCV_DLL_EXPORT
#define FCV_API __declspec(dllexport) // dll生成方导出
#else
#define FCV_API __declspec(dllimport) // dll调用方导入
#endif
class Message {
public:
Message(int m) : message_(m) {}
void Display(const char* msg);
};
其中FCV_DLL_EXPORT在dll导出项目的属性中配置,配置后FCV_API被定义为 __declspec(dllexport),在第三方调用时则无需配置,FCV_API被定义为__declspec(dllimport)。在dll导出工程中因FCV_API被定义为__declspec(dllexport)标识,所以编译器不仅会生成shared_dll.dll,还会生成shared_dll.lib文件。第三方调用时把shared_dll.lib文件拷贝到第三方工程中并配置好路径即可构建成功(target_link_libraries(Test ${CMAKE_CURRENT_SOURCE_DIR}/lib/message.lib)),运行时则把shared_dll.dll拷贝到运行环境(否则会报找不到shared_dll.dll),目标文件即可运行。
注意:如果链接库文件时带路径,则必须加*.lib后缀,否则会链接失败。若第三方引用,则可link_directories(${path_lib})来添加库路径,链接时只需写名字即可。
3.extern导出函数的理解(不一定对)
当我们需要导出静态库时且静态库是由C编写,但我们又不想所有的接口都暴露给第三方,此时我们可以在将需要对外提供的接口申明为extern属性,不需要对外提供的接口申明为static类型,我理解申明为static的接口则不会导出到lib中。
4.总结
1.动态链接库中的.lib并不包含由.cpp生成的目标文件,目标文件都包含再.dll中,.lib仅仅是提供链接到.DLL的地址信息等。所以对于动态链接来说,.lib和.dll缺一不可。主要体现在:在编译时如果你加了.lib的依赖项,不会出任何问题,但运行时,若没有.dll,会提示找不到xx.dll的信息。
2. 对于静态库lib,索引和实现都在其中。这时不需要dll。
3. 静态链接的静态就是链接时把里面需要的东西抽取出来安排到你的exe文件中,以后运行你的exe的时候不再需要lib。
4. 动态链接的动态就是exe运行时,依赖于dll里面提供的功能,没有这个dll,你的exe无法运行。