嵌入式log日志框架实现

在嵌入式开发中,开发阶段打印日志是追踪BUG常用手段,但是一旦到发布阶段,用来打印的日志一般需要不体现在发布中----即不被用户看到,同时在发布的版本出现问题时,还能使用原来的log定位问题源,那么使用一般的print语句,就不合适了,现在给大家介绍一下好用的log用法和框架。
源码在此

一、宏定义log实现

先给大家简单介绍一下常用条件编译相关的预编译指令

#define           定义一个预处理宏
#undef            取消宏的定义
#if               编译预处理中的条件命令,相当于C语法中的if语句
#ifdef            判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef           与#ifdef相反,判断某个宏是否未被定义
#elif             若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else             与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif            #if, #ifdef, #ifndef这些条件命令的结束标志.
defined          与#if, #elif配合使用,判断某个宏是否被定义

那么使用宏定义头+ifdef语句就可一键开关所有log日志打印

#include <stdio.h>
#define LOGS1 1  //定义宏常量-是
#define LOGS 0   //定义宏常量-否
void main(){
	#ifdef LOGS1	
	printf("log print1\n");
	#endif
	
	#ifdef LOGS
	printf("log print2\n");
	#endif
	
	#ifdef LOGS1
	printf(“log print3\n");
	#endif
}

在这里插入图片描述

二、函数时宏定义log

将log处理过程变为函数,然后以宏定义全局控制
函数介绍:
vsnprintf()作用:
使用vsnprintf()用于向一个字符串缓冲区打印格式化字符串,且可以限定打印的格式化字符串的最大长度。此函数需要C99或者C++11及以上版本才能支持。

int vsnprintf (char * sbuf, size_t n, const char * format, va_list arg);
参数sbuf:用于缓存格式化字符串结果的字符数组
参数n:限定最多打印到缓冲区sbuf的字符的个数为n-1个,因为vsnprintf还要在结果的末尾追加\0。如果格式化字符串长度大于n-1,则多出的部分被丢弃。如果格式化字符串长度小于等于n-1,则可以格式化的字符串完整打印到缓冲区sbuf。一般这里传递的值就是sbuf缓冲区的长度。
参数format:格式化限定字符串
参数arg:可变长度参数列表
返回:成功打印到sbuf中的字符的个数,不包括末尾追加的\0。如果格式化解析失败,则返回负数。

#include <stdio.h>
#include <stdarg.h>
#define OPEN_LOGS2 1
#define LOG_LEVEL LOG_DEBUG

typedef enum
{
  LOG_DEBUG = 0,
  LOG_INFO,
  LOG_WARN,
  LOG_ERROR,
} E_LOGLEVEL;

char *ME_LOGLevelGet(const int level)
{
  if (level == LOG_DEBUG)
  {
    return "DEBUG";
  }
  else if (level == LOG_INFO)
  {
    return "INFO";
  }
  else if (level == LOG_WARN)
  {
    return "LOG_WARN";
  }
  else if (level == LOG_ERROR)
  {
    return "LOG_ERROR";
  }
  return "UNKNON";
}

void ME_LOG(const int level, const char* fun,const int line,const char *fmt, ...)
{
#ifdef OPEN_LOGS2
  va_list arg;        // 宏定义参数
  va_start(arg, fmt); // 获取可变参数列表的第一个参数的地址(arg是类型为va_list的指针,fmt是可变参数最左边的参数)
  char buf[1 + vsnprintf(NULL, 0, fmt, arg)];
  vsnprintf(buf, sizeof(buf), fmt, arg);
  va_end(arg); // 清空va_list可变参数列表
  if (level >= LOG_LEVEL)
    printf("[%s][%s %d]%s\n", ME_LOGLevelGet(level),fun,line,buf);
#endif
}

#define EMLog(level,fmt...) ME_LOG(level,__FUNCTION__,__LINE__,fmt)		
//在这里定义是因为函数ME_LOG的定义范围,__FUNCTION__,__LINE__是内部参数定义,能够显示代码所在函数与行数

void main()
{
  main1();
  int a = 10, b = 11;
  EMLog(LOG_DEBUG, "app start");
  EMLog(LOG_INFO, "A= %d", a);
  EMLog(LOG_WARN, "app LOG_WARN");
  EMLog(LOG_ERROR, "app LOG_ERROR");
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值