1.前言
本篇博客一个使用 宏 的方式来配置代码的 Debug 与 Release 版本之间的差异。建议为每一个文件都配备单独的宏,方便进行更细粒度的控制。
2.编程框架
Debug 版本的需求:
- 能够在程序发生错误时输出相应的 error code,最好能够带有颜色高亮。
- 能够方便的移除,在 Release 版本中能够一键去除所有的 Debug 输出。
下面的代码是一段通用的版本控制的宏命令,但是这些宏在添加时比较麻烦,每次都需要输入这三段内容。所以我想要介绍一种我感觉比较好的版本控制框架。
#ifdef DEBUG
// debug version content
#else
// release version content
#endif
【1】颜色字。
- 对于人眼的注意力机制的完美适配,会优先注意到颜色和高亮的位置。
- 通过如下的宏定义就能够使用 PRINTCOLOR(CMD_RED, “errorcode %d”, errorcode); 的方式来输出带有颜色的信息。
// below is for debug output
#define CMD_RED FOREGROUND_RED
#define CMD_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
#define CMD_YELLOW FOREGROUND_RED |FOREGROUND_GREEN
#define CMD_GREEN FOREGROUND_GREEN
#define CMD_BLUE FOREGROUND_BLUE
#define CMD_PINK FOREGROUND_RED | FOREGROUND_BLUE
#define CMD_CYAN FOREGROUND_GREEN | FOREGROUND_BLUE
#define SETCOLOR(color) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
#define PRINTCOLOR(color, str, ...) SETCOLOR(color); printf(str, ##__VA_ARGS__); SETCOLOR(CMD_WHITE);
【2】DBG宏定义。
- 对于每一个文件,都定义一个 DBG 的宏。通过#ifdef——#else来进行控制宏的不同版本。
- 当宏未定义时,将相应的 PRINT 宏定义为空,这时其中的内容不会被调用,会被编译器优化。
// for debug info in Common
#ifdef DBG_COMMON
#define PRINT_COMMON PRINTCOLOR
#else
#define PRINT_COMMON
#endif
【3】THREE_COMBO宏定义
- 考虑到在 Windows 中一般函数发生错误后需要调用 GetLastError 函数来获取错误代码,所以编写下面的输出三连,能够将有用信息都进行输出,同时为了能够有效的进行 文件级 的粒度控制,所以定义了一个母版宏 THREE_COMBO。
#define THREE_COMBO(name, func) \
PRINT_##name(CMD_RED, "Fail to call the "); \
PRINT_##name(CMD_WHITE, #func"."); \
PRINT_##name(CMD_YELLOW, "Error code is 0x%x. line : %d\n", GetLastError(), __LINE__);
- 通过将母版宏进行实例化,得到每一个文件的宏,这样在该文件中使用对应的宏来输出 Debug 信息。而在 Release 版中,由于 PRINT 宏被定义为了空,所以 THREE_COMBO 中的内容会被编译器优化掉。
#define THREE_COMBO_COMMON(func) THREE_COMBO(COMMON, func)
3. 使用例子
// common.h
#ifndef COMMON_H
#define COMMON_H
#include <windows.h>
// below is for debug output
#define CMD_RED FOREGROUND_RED
#define CMD_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
#define CMD_YELLOW FOREGROUND_RED |FOREGROUND_GREEN
#define CMD_GREEN FOREGROUND_GREEN
#define CMD_BLUE FOREGROUND_BLUE
#define CMD_PINK FOREGROUND_RED | FOREGROUND_BLUE
#define CMD_CYAN FOREGROUND_GREEN | FOREGROUND_BLUE
#define SETCOLOR(color) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
#define PRINTCOLOR(color, str, ...) SETCOLOR(color); printf(str, ##__VA_ARGS__); SETCOLOR(CMD_WHITE);
#define THREE_COMBO(name, func) PRINT_##name(CMD_RED, "Fail to call the ");PRINT_##name(CMD_WHITE, #func".");PRINT_##name(CMD_YELLOW, "Error code is 0x%x. line : %d\n", GetLastError(), __LINE__);
// for debug info in Common
#ifdef DBG_COMMON
#define PRINT_COMMON PRINTCOLOR
#else
#define PRINT_COMMON
#endif
#endif
// common.cpp
#include "common.h"
#define DBG_COMMON //if in release comment this definition
int main() {
if(GetCurrentProcess() == FALSE) {
// use the encapsulated output
THREE_COMBO_COMMON(GetCurrentProcess);
// if you want output something else
PRINT_COMMON(CMD_CYAN, "good very %d\n", 1);
}
}