简单的QDebug
封装
以前习惯了使用qDebug()
的<<
来打印调试输出. 但是新公司是Linux的程序, 默认它会打印到控制台上, 这就很令人讨厌了. 如果直接关掉QDebug
, 又会让别的也用不了. 就自然想能不能通过DEBUG
和RELEASE
来区分. 然后使用<<
, 没法简单的做这件事情. 就想简单地将它封装一下, 封装成函数调用的方式. 想起很早以前玩过的C语言宏的花招, 试了两下就试出来了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #define CONCATE(x,y) x##y #define GET_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, n, ...) n #define GET_ARG_COUNT(...) GET_NTH_ARG(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define _dbg_show(arg) << arg #define _DEBUG_1(f, arg) f(arg) #define _DEBUG_2(f, arg, ...) f(arg) _DEBUG_1(f, __VA_ARGS__) #define _DEBUG_3(f, arg, ...) f(arg) _DEBUG_2(f, __VA_ARGS__) #define _DEBUG_4(f, arg, ...) f(arg) _DEBUG_3(f, __VA_ARGS__) #define _DEBUG_5(f, arg, ...) f(arg) _DEBUG_4(f, __VA_ARGS__) #define _DEBUG_6(f, arg, ...) f(arg) _DEBUG_5(f, __VA_ARGS__) #define _DEBUG_7(f, arg, ...) f(arg) _DEBUG_6(f, __VA_ARGS__) #define _DEBUG_8(f, arg, ...) f(arg) _DEBUG_7(f, __VA_ARGS__)
#define _DEBUG_X(i) CONCATE(_DEBUG_, i) #define _DEBUG_Y(...) _DEBUG_X(GET_ARG_COUNT(__VA_ARGS__))(_dbg_show, __VA_ARGS__)
#ifdef QT_DEBUG #define SDEBUG(...) qDebug() << "[" << __FUNCTION__ << "]: " _DEBUG_Y(__VA_ARGS__) #define SWARN(...) qWarning() << "[" << __FUNCTION__ << "]: " _DEBUG_Y(__VA_ARGS__) #else #define SDEBUG(...) #define SWARN(...) qWarning() << "[" << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << "]: " _DEBUG_Y(__VA_ARGS__) #endif
|
这样, 就可以在Release版本下将SDEBUG
定义成空了.
主要是两个技巧.
一个是GET_ARG_COUNT
, 它和GET_NTH_ARG
配合, 量出参数的个数. 这里, GET_NTH_ARG
就像是一个最大刻度为8的尺子, 组多量出8个参数. 这个宏最多支持8个参数, 如果想做, 只要往上加就可以了.
还有一个是CONCATE
这个宏, 在想出这个方法之前, _DEBUG_X
是直接这么写的: #define _DEBUG_X(i) _DEBUG_##i
, 但是这样怎么也无法正确展开. 最后相处这么一招, 用一个看似多余的宏来确保实现二次展开操作.
至于DEBUG_1, DEBUG_2, ...
, 则是手工实现的递归展开的形式, 同样就是简单的展开到8级.
要说为何不用qInstallMessageHandler
? 这个就很麻烦, 因为我的程序是一个主程序框架的一个插件, 我总不能去动整个软件吧.
要问别人用什么日志? 他们使用的是一个改造自spdlog, 语法类似于format
语法的调试输出工具, 我是很不习惯更不喜欢在调试时用format
这种语法, 因为你要记住在格式化串里面写花括号, 一旦忘记了, 就出不来了. 另一个问题是繁琐. 只有那种需要记录到日志文件中的信息, 我才会使用它. 比如说, 加入要打印a
的值, 我们需要这么写: log("a={}", a);
. 而使用宏, 我们可以简单地再定义一个:
1
| #define TSHOW(a) #a":=" << a << ", "
|
这样, 我们只需要这样用: SDEBUG(SHOW(a))
就可以打印出a=...
的效果了.
当然, 这么写很粗糙, 最后总是有一个逗号留着. 但是, 反正是调试, 调试好了就删掉了, 有啥关系呢.