频繁调用的情况下,宏定义日志接口是一种编程技巧。
一段使用宏定义日志接口的代码:
#include <stdarg.h>
#include <string.h>
#ifdef NMEDIA_SUPPORT_MINILOG
#include "minilogger/log.h"
#endif
#include "rkmedia_common.h"
#define LOG_LEVEL_ERROR 0
#define LOG_LEVEL_WARN 1
#define LOG_LEVEL_INFO 2
#define LOG_LEVEL_DBG 3
#ifndef MOD_TAG
#define MOD_TAG RK_ID_SYS
#endif
extern short g_level_list[RK_ID_BUTT];
extern int nmedia_log_method;
extern const char *mod_tag_list[RK_ID_BUTT];
#define LOG_LEVEL_JUDGE(FILTER_LEVEL) \
{ \
if (g_level_list[MOD_TAG] < FILTER_LEVEL) \
break; \
}
#ifdef NMEDIA_SUPPORT_MINILOG
#define NMEDIA_LOGE(format, ...) \
do { \
LOG_LEVEL_JUDGE(LOG_LEVEL_ERROR); \
minilog_error("[NMEDIA][%s][Error]:" format, mod_tag_list[MOD_TAG], \
##__VA_ARGS__); \
} while (0)
#define NMEDIA_LOGW(format, ...) \
do { \
LOG_LEVEL_JUDGE(LOG_LEVEL_WARN); \
minilog_warn("[NMEDIA][%s][Warn]:" format, mod_tag_list[MOD_TAG], \
##__VA_ARGS__); \
} while (0)
#define NMEDIA_LOGI(format, ...) \
do { \
LOG_LEVEL_JUDGE(LOG_LEVEL_INFO); \
minilog_info("[NMEDIA][%s][Info]:" format, mod_tag_list[MOD_TAG], \
##__VA_ARGS__); \
} while (0)
#define NMEDIA_LOGD(format, ...) \
do { \
LOG_LEVEL_JUDGE(LOG_LEVEL_DBG); \
minilog_debug("[NMEDIA][%s][Debug]:" format, mod_tag_list[MOD_TAG], \
##__VA_ARGS__); \
} while (0)
#else // NMEDIA_SUPPORT_MINILOG
#define NMEDIA_LOGE(format, ...) \
do { \
LOG_LEVEL_JUDGE(LOG_LEVEL_ERROR); \
fprintf(stderr, "[NMEDIA][%s][Error]:" format, mod_tag_list[MOD_TAG], \
##__VA_ARGS__); \
} while (0)
#define NMEDIA_LOGW(format, ...) \
do { \
LOG_LEVEL_JUDGE(LOG_LEVEL_WARN); \
fprintf(stderr, "[NMEDIA][%s][Warn]:" format, mod_tag_list[MOD_TAG], \
##__VA_ARGS__); \
} while (0)
#define NMEDIA_LOGI(format, ...) \
do { \
LOG_LEVEL_JUDGE(LOG_LEVEL_INFO); \
fprintf(stderr, "[NMEDIA][%s][Info]:" format, mod_tag_list[MOD_TAG], \
##__VA_ARGS__); \
} while (0)
#define NMEDIA_LOGD(format, ...) \
do { \
LOG_LEVEL_JUDGE(LOG_LEVEL_DBG); \
fprintf(stderr, "[NMEDIA][%s][Debug]:" format, mod_tag_list[MOD_TAG], \
##__VA_ARGS__); \
} while (0)
#endif // NMEDIA_SUPPORT_MINILOG
宏日志的好处:
-
性能优化:宏定义在预处理阶段进行替换,因此编译器将宏定义的日志函数直接替换为实际的日志函数调用,从而避免了函数调用的开销。对于频繁调用情况会显著提高程序的性能。
-
条件编译:使用宏定义,可以在不同的编译条件下选择不同的日志函数实现。例如,可以根据系统环境或者编译器环境的不同选择不同的底层日志实现。也能够做到可以在调试版本中使用更详细的日志输出,而在发布版本中只输出错误日志。
- 这段代码中就所有体现
NMEDIA_SUPPORT_MINILOG
这个宏可以在cmake中事先定义或者不定义,通过它可以决定日志底层接口使用哪个。
- 这段代码中就所有体现
-
灵活性:宏定义可以接受可变参数,这使得日志函数可以接受不同数量的参数,从而提供了更大的灵活性。例如,可以使用
printf
风格的格式字符串来格式化日志消息。 -
易于修改:由于宏定义是预处理器指令,因此可以在不修改源代码的情况下修改日志函数的行为。例如,可以通过修改宏定义中的日志级别判断条件来控制日志的输出级别。
g_level_list[MOD_TAG]
代表某一个模块等级
-
代码复用:宏定义定义在头文件中,在不同的源文件中复用。日志宏的实现可以在多个模块中共享,从而提高了代码的复用性。