在 Qt 项目中使用 spdlog 的全攻略
目录
1. 准备工作:安装 spdlog
方法一:使用 CMake 的 FetchContent(推荐)
方法二:手动下载并添加到项目中
2. 在 Qt 项目中集成 spdlog
a. 初始化 spdlog
b. 在 Qt 的各个部分使用 spdlog
3. 基本使用示例
4. 高级配置:多种输出目标和格式化
a. 多种 Sink
b. 自定义格式化
5. 异步日志记录
6. 在 Qt 中处理线程安全
7. 常见问题与解决方案
问题1:日志文件没有生成或写入
问题2:日志级别不正确
问题3:异步日志丢失日志消息
1. 准备工作:安装 spdlog
首先,我们需要将 spdlog
添加到你的 Qt 项目中。spdlog
是一个头文件库,你可以通过以下几种方式来获取它:
方法一:使用 CMake 的 FetchContent(推荐)
如果你的 Qt 项目使用 CMake 构建,这是最简单的方法。
# 在你的 CMakeLists.txt 文件中添加以下内容cmake_minimum_required(VERSION 3.14)
project(MyQtApp)set(CMAKE_CXX_STANDARD 17)# 引入 Qt
find_package(Qt5 COMPONENTS Widgets REQUIRED)# 使用 FetchContent 下载 spdlog
include(FetchContent)
FetchContent_Declare(spdlogGIT_REPOSITORY https://github.com/gabime/spdlog.gitGIT_TAG v1.11.0 # 选择一个稳定的版本
)
FetchContent_MakeAvailable(spdlog)# 添加可执行文件
add_executable(MyQtApp main.cpp mainwindow.cpp mainwindow.h mainwindow.ui)# 链接 Qt 和 spdlog
target_link_libraries(MyQtApp PRIVATE Qt5::Widgets spdlog::spdlog)
方法二:手动下载并添加到项目中
- 前往 spdlog 的 GitHub 仓库。
- 下载最新的 release 版本(ZIP 文件)。
- 将
spdlog/include
文件夹复制到你的项目目录中(例如,放在external/spdlog
)。 - 在你的
CMakeLists.txt
中添加如下内容:
# 添加 spdlog 的包含路径
include_directories(${CMAKE_SOURCE_DIR}/external/spdlog/include)# 假设你不需要构建 spdlog 库,而是作为头文件库使用
add_executable(MyQtApp main.cpp mainwindow.cpp mainwindow.h mainwindow.ui)# 链接 Qt
target_link_libraries(MyQtApp PRIVATE Qt5::Widgets)
2. 在 Qt 项目中集成 spdlog
假设你已经将 spdlog
添加到项目中,接下来我们来配置和使用它。
a. 初始化 spdlog
在你的 Qt 项目的入口处( main.cpp
),初始化 spdlog
:
// main.cpp
#include <QApplication>
#include "mainwindow.h"
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();// 初始化 spdlogtry {// 创建一个同时输出到控制台和文件的 loggerauto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/myapp.log", true);std::vector<spdlog::sink_ptr> sinks {console_sink, file_sink};auto logger = std::make_shared<spdlog::logger>("multi_sink", sinks.begin(), sinks.end());// 设置全局日志器spdlog::set_default_logger(logger);spdlog::set_level(spdlog::level::info); // 设置日志级别spdlog::flush_on(spdlog::level::info); // 设置自动刷新级别}catch (const spdlog::spdlog_ex &ex) {fprintf(stderr, "日志初始化失败: %s\n", ex.what());return 1;}return a.exec();
}
b. 在 Qt 的各个部分使用 spdlog
在你的 MainWindow
或其他类中使用 spdlog
来记录日志:
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <spdlog/spdlog.h>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);spdlog::info("应用程序已启动");
}MainWindow::~MainWindow()
{spdlog::info("应用程序正在关闭");delete ui;
}void MainWindow::on_someButton_clicked()
{spdlog::info("按钮被点击了!");// 你的其他代码
}void MainWindow::on_errorCondition()
{spdlog::error("发生了一个错误!");// 错误处理代码
}
3. 基本使用示例
让我们来看一个简单的示例,展示如何在 Qt 应用中记录不同级别的日志。
// 在你的某个函数中
void MainWindow::performTask()
{spdlog::debug("任务开始");spdlog::info("任务进行中");if (/* 某个条件 */) {spdlog::warn("遇到警告条件");}try {// 可能会抛出异常的代码}catch (const std::exception &e) {spdlog::error("异常捕获: {}", e.what());}spdlog::critical("任务完成,但有严重问题!");
}
4. 高级配置:多种输出目标和格式化
a. 多种 Sink
spdlog
允许你将日志输出到多个目标(sinks),比如文件、控制台、甚至网络。
// 仅输出到控制台
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();// 仅输出到文件
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/myapp.log", true);// 创建包含多个 sinks 的 logger
std::vector<spdlog::sink_ptr> sinks {console_sink, file_sink};
auto logger = std::make_shared<spdlog::logger>("multi_sink", sinks.begin(), sinks.end());// 设置为默认 logger
spdlog::set_default_logger(logger);
b. 自定义格式化
你可以定义日志的输出格式,使其更符合你的需求。
// 设置日志格式
// 例如: [2024-04-27 12:34:56.789] [info] [main.cpp:42] 这是一个信息日志
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%s:%#] %v");
常用的格式化标识:
%Y-%m-%d %H:%M:%S
:日期和时间%l
:日志级别(info, error, etc.)%s
:源文件名%#
:源代码行号%v
:日志消息
5. 异步日志记录
对于需要高性能的应用,异步日志记录是个不错的选择。spdlog
提供了简便的异步日志支持。
#include <spdlog/async.h> // 需要包含这个头文件
#include <spdlog/sinks/basic_file_sink.h>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();try {// 初始化线程池,队列大小为8192,线程数为1spdlog::init_thread_pool(8192, 1);// 创建一个异步文件日志器auto async_file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/async_log.txt", true);auto async_logger = std::make_shared<spdlog::async_logger>("async_logger", async_file_sink, spdlog::thread_pool(), spdlog::async_overflow_policy::block);// 将异步 logger 添加到默认 loggerspdlog::register_logger(async_logger);spdlog::set_default_logger(async_logger);spdlog::set_level(spdlog::level::info);spdlog::flush_on(spdlog::level::info);}catch (const spdlog::spdlog_ex &ex) {fprintf(stderr, "日志初始化失败: %s\n", ex.what());return 1;}return a.exec();
}
6. 在 Qt 中处理线程安全
Qt 应用通常涉及多线程操作,spdlog
是线程安全的,这意味着你可以在多个线程中安全地记录日志而无需担心竞争条件。
// 在主线程中
void MainWindow::startBackgroundTask()
{std::thread([=]() {spdlog::info("后台任务开始");// 执行一些耗时操作spdlog::info("后台任务完成");}).detach();
}
7. 常见问题与解决方案
问题1:日志文件没有生成或写入
解决方案:
- 确保指定的日志目录存在。例如,如果你指定
logs/myapp.log
,确保logs
目录已创建。 - 检查文件路径是否正确,尤其是在不同操作系统上的路径格式。
问题2:日志级别不正确
解决方案:
- 确保设置了正确的日志级别。例如,默认级别可能是
info
,如果你使用debug
级别的日志,可能不会输出。通过spdlog::set_level(spdlog::level::debug);
来调整。
问题3:异步日志丢失日志消息
解决方案:
-
在应用程序退出前,调用
spdlog::shutdown();
确保所有日志消息被写入。int main(int argc, char *argv[]) {// 初始化代码...int result = a.exec();spdlog::shutdown(); // 确保所有日志被写入return result; }
参考:
日志的艺术:深入理解 spdlog-CSDN博客
相关文章:
在 Qt 项目中使用 spdlog 的全攻略
目录 1. 准备工作:安装 spdlog 方法一:使用 CMake 的 FetchContent(推荐) 方法二:手动下载并添加到项目中 2. 在 Qt 项目中集成 spdlog a. 初始化 spdlog b. 在 Qt 的各个部分使用 spdlog 3. 基本使用示例 4. …...

vue的el-button防止重复点击
这样效果仅生效在按钮上...

消息中间件 Kafka 快速入门与实战
1、概述 最近感觉上班实在是太无聊,打算给大家分享一下Kafka的使用,本篇文章首先给大家分享三种方式搭建Kafka环境,接着给大家介绍kafka核心的基础概念以及Java API的使用,最后分享一个SpringBoot的集成案例,希望对大…...

【Unity服务】如何使用Unity Version Control
Unity上的线上服务有很多,我们接触到的第一个一般就是Version Control,用于对项目资源的版本管理。 本文介绍如何为项目添加Version Control,并如何使用,以及如何将项目与Version Control断开链接。 其实如果仅仅是对项目资源进…...
C++ --- 静态多态和动态多态
静态多态和动态多态 静态多态动态多态总结 静态多态和动态多态是面向对象编程中多态性的两种主要形式,它们在实现方式、绑定时机以及应用场景上存在一些显著的区别。 静态多态 静态多态,也被称为编译时多态,是指在编译阶段就已经确定了对象调…...
华为vxlan
VXLAN是什么?VXLAN与VLAN之间有何不同? - 华为...

队列及笔试题
队列 先进先出 使用单链表进行队尾插入 队头删除 其中带头结点直接尾插,不带头结点第一次操作要判断一下 但是带头结点需要malloc和free 函数传需要修改的参数方法 1、二级指针 2、带哨兵位的头结点 3、返回值 4、如果有多个值,用结构体封装起来…...

JAVA TCP协议初体验
文章目录 一、需求概述二、设计选择三、代码结构四、代码放送五、本地调试1. 服务端日志2. 客户端日志3. 断线重连日志 六、服务器部署运行1. 源码下载2. 打包镜像3. 运行容器 一、需求概述 最近开发某数据采集系统,系统整体的数据流程图如下: #mermaid…...

sqlserver迁移数据库文件存储位置
业务背景:由于C盘爆满,需要将数据库文件迁移到别处比如D盘 下面以某一个数据库转移为示例:(可以用SSMS工具,新建查询配合使用) 1.查询数据库文件存储路径 sql语句: -- 查询路径 USE QiangTes…...
配置项取值给静态类用
在 Java 中,如果要从 application.yml 文件中取值并供静态类使用,可以考虑以下几种方法: 一、使用 Spring 的 Environment 类 1. 首先确保你的项目是一个 Spring 项目,并且配置文件被正确加载。 2. 在需要获取配置值的类中注入…...

【vs code(cursor) ssh连不上服务器】但是 Terminal 可以连上,问题解决 ✅
问题描述 通过 vs code 的 ssh 原本方式无法连接,但是通过 Terminal 使用相同的 bash 却可以连接上服务器。 ssh -p 4xx username14.xxx.3 问题解决方法 在 vs code 的 config 里,将该服务器(14.xxx.3)的相关配置全部清空或注释…...

Go基础学习06-Golang标准库container/list(双向链表)深入讲解;延迟初始化技术;Element;List;Ring
基础介绍 单向链表中的每个节点包含数据和指向下一个节点的指针。其特点是每个节点只知道下一个节点的位置,使得数据只能单向遍历。 示意图如下: 双向链表中的每个节点都包含指向前一个节点和后一个节点的指针。这使得在双向链表中可以从前向后或从后…...

多层时间轮原理以及使用
文章目录 背景常用定时器实现 任务队列时间轮介绍基本结构指针移动定时任务插入循环任务插入代码示例 多层时间轮使用流程 代码 背景 在软件开发中,定时器是一个极为常用的组件,它发挥着至关重要的作用。通过定时器,开发者能够精确地控制程序…...

鸿蒙HarmonyOS开发生态
1、官网 华为开发者联盟-HarmonyOS开发者官网,共建鸿蒙生态 2、开发工具IDE下载及使用 https://developer.huawei.com/consumer/cn/ 3、使用帮助文档 4、发布到华为应用商店 文档中心...
vue中使用jsencrypt加密
vue中封装并使用jsencrypt加密 一般在项目搭建过程中用户注册、登录、修改密码、重置密码等功能都需要用到密码加密的功能,所以把jsencrypt进行封装使用,使代码更加简洁,流程如下: 1、安装jsencrypt npm install jsencrypt2、在…...
SpirngBoot核心思想之一AOP
简介: AOP(Aspect-Oriented Programming,面向切面编程) 是一种用于解决软件系统中横切关注点的编程范式。在企业级开发中,很多非业务功能(如日志、事务、权限、安全等)需要在多个模块中执行&am…...

足球预测推荐软件:百万数据阐述百年足球历史-大数据模型量化球员成就值
我开始创建这个模型是从梅西22世界杯夺冠第二天开始准备的,当时互联网上充斥了太多了个人情感的输出,有的人借题对C罗冷嘲热讽,有的人质疑梅西的阿根廷被安排夺冠不配超越马拉多纳做GOAT。作为一个从2002年开始看球的球迷,说实话有…...

AD中如何批量修改丝印的大小,节省layout时间
先选中一个元器件的丝印,然后右键,选择“查找相似项” 直接点击OK,这时会发现所有的丝印都会被选中 然后点击右上角的按键,修改其属性。...

Ps:堆栈
将多张类似的图像图层堆叠在一起形成图像堆栈 Stack,通过应用不同的堆栈模式,可以从这些图像中提取有用的信息或达到特定的视觉效果。 Photoshop 中的堆栈技术被广泛应用于摄影后期处理、科学研究、环境监测与分析等领域。 例如,它常用于减少…...
獨立IP和共用IP有什麼區別?
什麼是獨立IP? 獨立IP指的是一個IP地址專屬於一個用戶或設備。無論是網站、伺服器還是其他線上服務,獨立IP都意味著該IP地址不會與其他用戶或設備共用。獨立IP通常用於需要高安全性和穩定性的場景,比如企業網站、電子商務平臺和需要SSL證書的…...

【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...

ArcGIS Pro+ArcGIS给你的地图加上北回归线!
今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等,设置经线、纬线都以10间隔显示。 2、需要插入背会归线…...

Redis上篇--知识点总结
Redis上篇–解析 本文大部分知识整理自网上,在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库,Redis 的键值对中的 key 就是字符串对象,而 val…...

【Java多线程从青铜到王者】单例设计模式(八)
wait和sleep的区别 我们的wait也是提供了一个还有超时时间的版本,sleep也是可以指定时间的,也就是说时间一到就会解除阻塞,继续执行 wait和sleep都能被提前唤醒(虽然时间还没有到也可以提前唤醒),wait能被notify提前唤醒…...

VSCode 没有添加Windows右键菜单
关键字:VSCode;Windows右键菜单;注册表。 文章目录 前言一、工程环境二、配置流程1.右键文件打开2.右键文件夹打开3.右键空白处打开文件夹 三、测试总结 前言 安装 VSCode 时没有注意,实际使用的时候发现 VSCode 在 Windows 菜单栏…...