今天,分享一个我自己用的、极简的log模块:log颜色可设置,带时间戳、文件、行号、函数。这个log模块仅包含两个文件:log.h 和 log.c。
一、log模块代码log.h:
#ifndef LOG_H #define LOG_H #ifdef __cplusplus extern "C" { #endif #define LOG_BUF_SIZE 1024 typedef long long (*get_sys_time_ms_def)(void); enum log_color { COLOR_NULL = 0, RED = 1, GREEN = 2, YELLOW = 3, BLUE = 4 }; void log_print(enum log_color color, const char *file, int line, const char *func, const char* fmt, ...); void log_time_register(get_sys_time_ms_def p_get_sys_time_ms); #define LOG_D(...) log_print(BLUE, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) #ifdef __cplusplus } #endif #endif
log.c:
#include <stdio.h> #include <stdarg.h> #include "log.h" static long long default_get_sys_time_ms(void) { return (long long)0; } static get_sys_time_ms_def s_get_sys_time_ms = default_get_sys_time_ms; void log_time_register(get_sys_time_ms_def p_get_sys_time_ms) { s_get_sys_time_ms = p_get_sys_time_ms; } void log_print(enum log_color color, const char *file, int line, const char *func, const char* fmt, ...) { va_list ap; char buf[LOG_BUF_SIZE] = {0}; long long time = s_get_sys_time_ms(); va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); switch(color) { case COLOR_NULL: printf("<%lld ms>[%s:%d %s] %s ", time, file, line, func, buf); break; case RED: printf("\033[31m<%lld ms>[%s:%d %s] %s\033[0m", time, file, line, func, buf); break; case GREEN: printf("\033[32m<%lld ms>[%s:%d %s] %s\033[0m", time, file, line, func, buf); break; case YELLOW: printf("\033[33m<%lld ms>[%s:%d %s] %s\033[0m", time, file, line, func, buf); break; case BLUE: printf("\033[34m<%lld ms>[%s:%d %s] %s\033[0m", time, file, line, func, buf); break; default: break; } }
其中,默认打印ms级的系统时间。因为不同的平台(Linux、Windows、STM32等),获取系统时间的方式都不一样。
使用时,再根据不同的平台自己定义一个获取系统时间的函数,以注册的方式进行绑定。不注册获取时间函数也不影响使用,时间戳打印为0。
二、log模块测试1、Linux平台log_test.c:
#include <stdio.h> #include <sys/time.h> #include "log.h" static long long linux_get_sys_time_ms(void) { long long time_ms = 0; struct timeval tv; gettimeofday(&tv, NULL); time_ms = (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000; return (long long)time_ms; } int main(void) { log_time_register(linux_get_sys_time_ms); char ch = 'a'; char str[10] = "ZhengN"; float float_val = 10.10; int num = 88; double double_val = 10.123456; LOG_D("字符为 %c \n", ch); LOG_D("字符串为 %s \n" , str); LOG_D("浮点数为 %f \n", float_val); LOG_D("整数为 %d\n" , num); LOG_D("双精度值为 %lf \n", double_val); LOG_D("八进制值为 %o \n", num); LOG_D("十六进制值为 %x \n", num); return 0; }
编译,运行:
第18行屏蔽掉:
2、Windows平台log_test.c:
#include <stdio.h> #include <windows.h> #include "log.h" static long long win_get_sys_time_ms(void) { long long time_ms = 0; time_ms = GetTickCount(); return time_ms; } void test(void) { LOG_D("Hello world\n"); } int main(void) { log_time_register(win_get_sys_time_ms); char ch = 'a'; char str[10] = "ZhengN"; float float_val = 10.10; int num = 88; double double_val = 10.123456; LOG_D("字符为 %c \n", ch); LOG_D("字符串为 %s \n" , str); LOG_D("浮点数为 %f \n", float_val); LOG_D("整数为 %d\n" , num); LOG_D("双精度值为 %lf \n", double_val); LOG_D("八进制值为 %o \n", num); LOG_D("十六进制值为 %x \n", num); test(); return 0; }
编译,运行: