此 log 移植自乐鑫esp32
源码如下:https://github.com/i-wanglei/EasyLog
此日志系统具有以下特点:
- log输出等级可配置
- 不同log等级可采用不同颜色输出
- 使用简单
- 格式通用,可打印log文件信息
- 可支持时间戳输出
针对此 log 进行优化,可使用在嵌入式mcu平台,是一种不错的 log 输出方式
此 log 中包含一些关于 c 语言的一些冷门的重要知识,特再次作记录说明~!
源文件如下(为了方便说明,将文件集中在一个文件中):
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#define LOG_LOCAL_LEVEL 3
typedef enum {
LOG_NONE, /*!< No log output */
LOG_ERROR, /*!< Critical errors, software module can not recover on its own */
LOG_WARN, /*!< Error conditions from which recovery measures have been taken */
LOG_INFO, /*!< Information messages which describe normal flow of events */
LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
} log_level_t;
#define LOG_FORMAT(letter, format) #letter " (%d) %s: " format "\n"
#define LOGE( tag, format, ... ) if (LOG_LOCAL_LEVEL >= LOG_ERROR) {
log_write(LOG_FORMAT(E, format), log_timestamp(), tag, ##__VA_ARGS__); }
#define LOGW( tag, format, ... ) if (LOG_LOCAL_LEVEL >= LOG_WARN) {
log_write(LOG_FORMAT(W, format), log_timestamp(), tag, ##__VA_ARGS__); }
#define LOGI( tag, format, ... ) if (LOG_LOCAL_LEVEL >= LOG_INFO) {
log_write(LOG_FORMAT(I, format), log_timestamp(), tag, ##__VA_ARGS__); }
#define LOGD( tag, format, ... ) if (LOG_LOCAL_LEVEL >= LOG_DEBUG) {
log_write(LOG_FORMAT(D, format), log_timestamp(), tag, ##__VA_ARGS__); }
#define LOGV( tag, format, ... ) if (LOG_LOCAL_LEVEL >= LOG_VERBOSE) {
log_write(LOG_FORMAT(V, format), log_timestamp(), tag, ##__VA_ARGS__); }
unsigned int log_timestamp(void);
void log_write(const char* format, ...) __attribute__ ((format (printf, 1, 2)));
void log_write(const char *format, ...)
{
va_list arg;
va_start(arg, format);
vprintf(format, arg);
va_end(arg);
}
unsigned int log_timestamp(void)
{
return 0;
}
int main()
{
int ret = 0;
LOGE("test", "hello %d", ret);
return 0;
}
执行结果如下:
补充说明:
-
通过修改宏定义
#define LOG_LOCAL_LEVEL 3
可以实现的输出等级的调整,范围0 - 5 -
void log_write(const char *format, ...)
函数:
a. 内部采用格式化输出,达到与printf的作用,此处不做深入讲解,理解为printf就行 -
unsigned int log_timestamp(void)
函数:
a. 可根据各自的平台,将事件戳作为返回值输出返回 -
__attribute__ ((format (printf, 1, 2)))
a. 用来作语法检查/ 用法原型 // archetype:为按照那种风格进行校验,如printf/scanf等 // string-index:格式化format字符串所在的位置,如void test(testA, format,...),此时为2 // first-to-check:第一个可变参数的位置,如void test(testA, format,...),此时为3 __attribute__((format(archetype, string-index, first-to-check)))
b. 详细内容可以参考:https://blog.csdn.net/u014630623/article/details/101107023
c. pass:分析时,可以先将此部分注释void log_write(const char* format, ...); // __attribute__ ((format (printf, 1, 2)));
-
#define LOG_FORMAT(letter, format) #letter " (%d) %s: " format "\n"
a. #的作用是将letter转化为字符串
b. 可以使用gcc main.c -E > debug
查看预编译LOGE("test", "hello %d", ret);
预编译结果为if (3 >= LOG_ERROR) { log_write("E" " (%d) %s: " "hello %d" "\n", log_timestamp(), "test"); };
c. 有关#和##关键字的使用可以参考:https://blog.csdn.net/dotphoenix/article/details/4345174