在实际应用中,我们需要动态导出特定的符号(有些接口不对外暴露,只内部适用)。
为什么动态库会隐藏函数/类?
__declspec
MSVC如何封装动态库
cmake和头文件如何写
// 指定外部可用的库
__declspec(dllexport)
// 调用
extern __declspec(dllimport)
``` // 动态库封装的cmakelist.txt if(WIN32) if(MSVC) add_definitions(-DUSE_SHARED) else() add_definitions(-DNO_MSVC) endif() endif()
// 静态库封装的cmakelist.txt if(WIN32) if(MSVC) add_definitions(-DUSE_STATIC) else() add_definitions(-DNO_MSVC) endif() endif()
// Qt的封装 #define Q_DECL_EXPORT __declspec(dllexport) #define Q_DECL_IMPORT __declspec(dllimport)
**其他编译器如何实现封装部分函数?**
- GCC4.0后,提供visibility属性,可以应用到函数、变量、模板以及C++类
#ifdef GNUC >= 4 #ifdef FBC_EXPORT #define FBC_API_PUBLIC attribute((visibility (“default”))) #define FBC_API_LOCAL attribute((visibility(“hidden”))) #else #define FBC_API_PUBLIC #define FBC_API_LOCAL #endif #else #error “—— requires gcc version >= 4.0 ——” #endif
**静态库__declspec()使用?**
使用MSVC
- 封装静态库:使用__declspec(dllexport)修饰
- 使用静态库:不能用__declspec(dllimport)修饰,因为找不到动态库
- 建议:静态库的代码dllexport、dllimport都不要用
**静态库隐藏符号功能**
gcc可以直接 -fvisibility=hidden
每个cpp文件为一个编译单元,单元有三类符号(不包含局部非静态程序变量):
- 全局符号
- 自己用的符号
- 依赖外部的符号
**编译阶段**:只要声明就可以
**链接阶段**:链接器就是把这些符号相互链接,少了那个都会链接失败。
静态库加载动态库后使用、动态库加载静态库后使用?
//Todo
静态库没有链接这个步骤,静态库如果用了其他静态库或者动态库需要手动链接。 动态库有链接步骤,链接静态库则把静态库全部放进来,链接动态库则只放入符号再程序启动时候链接。 动态库可以由多个程序共享, 节省内存,易于升级。静态库外部依赖少, 更易于部署。 ```