在前面的学习系列文章中,我们都是在单独的一个应用程序中使用 Easylogging++ 日志库。其实 Easylogging++ 日志库是可以共享给动态库、静态库以及应用程序共同使用的。在编写一些大型程序的时候,我们往往会把各个功能分别封装成一个动态库,然后再编写一个主程序来负责调用这些动态库就可以了。现在假设我们想在主程序和各个动态库中都使用 Easylogging++ 来记录日志,那么我们需要在主程序和各个动态库中的代码中都包含 Easylogging++ 的头文件,然后再分别设置主程序和各个动态库的日志配置。这是一个非常繁琐的事情,而且很容易把主程序和各个动态库中的日志配置成保存在同一个文件里,这可能会造成多个动态库同时对同一个日志文件进行写操作的情形,从而可能会使得日志内容乱成一团。但是因为主程序和各个动态库合并起来才算是一个完整的程序,我们又确实想把主程序和各个动态库中相同级别的的日志都保存在同一个文件中,那么我们只需要使用 Easylogging++ 的共享功能,就可以完美地满足我们的需求,并且还能避免上述所说的问题。

在 Easylogging++ 日志库的源码中,有一个名为 Storage 的类,这个类是负责维护 Easylogging++ 日志库数据的主要入口,比如日志记录器的管理,日志配置的管理等都是在 Storage 类中完成的。默认情况下,我们每调用一次初始化宏 INITIALIZE_EASYLOGGINGPP 就会创建一个 Storage 类对象,所以不同的程序就会有不同的 Storage 类对象在负责维护相应的日志记录器和日志配置。如果我们只创建一次 Storage 类对象,然后再将这个对象共享给其他使用 Easylogging++ 日志库的程序使用,那么就可以保证所有程序都在使用同一个 Storage 类对象维护的日志记录器和日志配置,如同在单独的应用程序中使用日志记录一样方便和安全。

为了使用共享的 Storage 类对象,在其他程序中我们不能用宏 INITIALIZE_EASYLOGGINGPP 来初始化日志库,应该改用以下两个宏定义中任意一个:

  • INITIALIZE_NULL_EASYLOGGINGPP
  • SHARE_EASYLOGGINGPP
如果使用宏 INITIALIZE_NULL_EASYLOGGINGPP ,那么必须用函数 el::Helpers::setStorage(el::base::type::StoragePointer) 来设置共享的 Storage 类对象,否则将会运行出错;如果使用宏 SHARE_EASYLOGGINGPP ,那么必须将共享的 Storage 类对象作为参数传递进去。在 Easylogging++ V9.80 的版本中,如果使用宏 SHARE_EASYLOGGINGPP 编译会出现错误,提示无法解析的外部符号,下面是定义该宏的源码:

[plain] view plaincopy print?
  1. #define SHARE_EASYLOGGINGPP(initializedStorage)\
  2. namespace el {\
  3. namespace base {\
  4. el::base::type::StoragePointer elStorage(initializedStorage);\
  5. }\
  6. el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\
  7. }
#define SHARE_EASYLOGGINGPP(initializedStorage)\namespace el {\namespace base {\el::base::type::StoragePointer elStorage(initializedStorage);\}\el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\}

解决编译出错的方法很简单,增加一个宏 ELPP_INITI_BASIC_DECLR 即可,下面是修改之后的代码:

[plain] view plaincopy print?
  1. #define SHARE_EASYLOGGINGPP(initializedStorage)\
  2. ELPP_INITI_BASIC_DECLR\
  3. namespace el {\
  4. namespace base {\
  5. el::base::type::StoragePointer elStorage(initializedStorage);\
  6. }\
  7. el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\
  8. }
#define SHARE_EASYLOGGINGPP(initializedStorage)\ELPP_INITI_BASIC_DECLR\namespace el {\namespace base {\el::base::type::StoragePointer elStorage(initializedStorage);\}\el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\}

其实,修改之后的代码就和另外一个宏 ELPP_INIT_EASYLOGGINGPP 的代码一模一样。有兴趣的小伙伴可以查看一下源码分别了解一下以下几个和初始化有关的宏定义:

  • INITIALIZE_EASYLOGGINGPP
  • ELPP_INIT_EASYLOGGINGPP
  • INITIALIZE_NULL_EASYLOGGINGPP
  • SHARE_EASYLOGGINGPP
最后通过一个完整的演示工程来说明如何只创建一个 Storage 类对象,然后再将该对象共享给其他工程使用。在演示工程有下面四个项目:
  • ShareEasylogging++项目,一个动态库工程,完成 Storage 类对象的创建,并提供获取该对象的接口,以便其他工程共享该对象。
  • ShareEasyloggingDll1项目,一个动态库工程,演示了如何使用宏 SHARE_EASYLOGGINGPP 和共享的 Storage 类对象完成初始化。
  • ShareEasyloggingDll2项目,一个动态库工程,演示了如何使用宏 SHARE_EASYLOGGINGPP 和共享的 Storage 类对象完成初始化。
  • ShareEasyloggingTest项目,演示工程主程序,演示了如何使用宏 INITIALIZE_NULL_EASYLOGGINGPP 和共享的 Storage 类对象完成初始化。
完整的演示工程代码下载:猛戳这里。

日志库EasyLogging++学习系列(11)—— 共享日志库相关推荐

  1. 日志库EasyLogging++学习系列(7)—— 记录方式详解

    在前面所列文章的演示代码中,其实已经展示了一部分记录日志的方式.为了使用方便,在 Easylogging++ 中,通过使用宏的集合来完成日志记录. 普通日志记录 对于普通的日志记录,我们可以选择以下两 ...

  2. 日志库EasyLogging++学习系列(10)—— 日志文件滚动

    在很多应用场合,我们是需要实现日志文件滚动的,特别是在一些长期运行的服务器程序中,如果把所有的日志都记录在一个文件之中,势必会造成日志文件越来越大.当日志内容很多的时候,万一哪天突然需要查询某个日志信 ...

  3. 日志库EasyLogging++学习系列(6)—— 日志记录器

    所有的日志都是由日志记录器完成的,日志记录器使用唯一的 ID(大小写敏感)来标识.在 Easylogging++ 中默认了三个现有的日志记录器: 默认日志记录器,其 ID 为:default 性能日志 ...

  4. 日志库EasyLogging++学习系列(5)—— 辅助配置功能

    正如前面<日志库EasyLogging++学习系列(3)-- 配置功能>文中最后提到的,在某些应用场景下,我们还需要通过其他的一些配置手段来辅助我们完成某些特殊功能,这些辅助配置手段包括设 ...

  5. 日志库EasyLogging++学习系列(3)—— 配置功能

    在前面的文章 <日志库Easylogging++学习系列(1) -- 简要介绍 >中,我们已经初步见识到了 Easylogging++ 日志库强大的配置功能.那么配置文件中各个字段的意义是 ...

  6. 日志库EasyLogging++学习系列(2)—— 日志级别

    在很多的C++日志库中,日志信息会根据严重性来划分级别,使用者可以设置严重性级别门阀值来控制日志的输出,即严重性级别在该门阀值以上的日志信息才进行记录.以此不同,在Easylogging++日志库中, ...

  7. 日志库EasyLogging++学习系列(4)—— 格式说明符

    在上一篇文章中,主要记录了如何使用 Easylogging++ 的配置功能,虽然已经用了很大的篇幅尽可能详细地加以记录,不过相信有些细心的小伙伴可能已经发现遗漏了些什么,请看下面两句摘自 my_log ...

  8. 日志库EasyLogging++学习系列(1)—— 简要介绍

    对于有开发经验的程序员来说,记录程序执行日志是一件必不可少的事情.通过查看和分析日志信息,不仅可以有效地帮助我们调试程序,而且当程序正式发布运行之后,更是可以帮助我们快速.准确地定位问题.在现在这个开 ...

  9. 日志库EasyLogging++学习系列(9)—— 性能跟踪功能

    性能跟踪是 Easylogging++ 其中一个非常显著的功能,而且使用起来也十分简单.如果在Windows平台下使用性能跟踪的话,其原理是基于 Windows API函数 GetSystemTime ...

最新文章

  1. 联邦学习应用思考:需求还是方法?
  2. flash TweenMax用法
  3. mac nginx apache mysql php 一键_Mac 下搭建 apache / nginx+php+mysql
  4. 网络流-最大流 dinic+当前弧优化(模板)
  5. 稍微有点难度的10道java面试题,你会几道?
  6. map 循环_被问到Spring循环依赖怎么解决?秀给面试官看!内附图解
  7. python类添加方法以及pow和cmp的使用
  8. tyvj——P3524 最大半连通子图
  9. 【图像加密】基于matlab混沌算法图像加密解密【含Matlab源码 1218期】
  10. Eclipse特色主题推荐——Marketplace
  11. 有哪些不错的数学、物理类的「闲书」?
  12. 深圳宝安学区房_查查吧深圳学区地图
  13. YARN动态资源池配置案例
  14. 连接树莓派后斐讯k2路由cpu占用100%
  15. 基督教 犹太  新教  东正教 天主教
  16. 2.14 Whisper和Swarm
  17. oracle百度坐标系火星转换,标准坐标系与火星坐标系(高德)百度坐标系之间互转...
  18. 【springcloud合集】04:新建Moudle——微服务提供者支付模块
  19. python 更换windows壁纸(简单)
  20. 什么是大数据?2022大数据时代

热门文章

  1. c++ 32位有符号的整数_【LeetCode】字符串分类字符串转换整数 (atoi)
  2. opencv 设置视频帧的分辨率“无效”
  3. wpf在异步中给前台赋值
  4. C#通过获取快捷方式指向目标的小示例触碰WMI
  5. apue 2013-03-14
  6. 文件流习题8.3 8.4
  7. BZOJ 1020——[SHOI2008]安全的航线flight
  8. “多态枚举”数值如何判断?
  9. 强大的.NET反编译工具Reflector及插件(转载)
  10. 首次写文章,分享一些渗透、安全工具