宏定义log输出
log输出宏定义
丈夫非无泪,不洒离别间。
首先看几个编译器预定义的变量
C&C++预处理器定义了几个对于程序调试很有用的名字:
__func__
存放函数的名字__FILE__
存放文件名的字符串字面值__LINE__
存放当前行号的整型字面值__TIME__
存放文件编译时间的字符串字面值__DATE__
存放文件编译日期的字符串字面值
示例:
void main()
{
printf("%s hello", __func__);
}
则会输出:
main hello
调试的时候非常方便看是哪里输出的:
看到这里懂了吧。那么想不想拥有它呢,接着看吧。
一、使用C++ 类特性的宏定义
这里我们需要定义一个类如下:
".h"
#define AHINFO\
AH_LOG::getinstance().printTitle(__func__, "Info").printS
#define AHWARNING\
AH_LOG::getinstance().printTitle(__func__, "Warning").printS
#define AHERROR\
AH_LOG::getinstance().printTitle(__func__, "Error").printS
class AH_LOG{
AH_LOG();
~AH_LOG();
public:
AH_LOG &printS(const char *fmt, ...);
AH_LOG &printTitle(const char *funcName, const char *type);
static AH_LOG &getinstance(); // 返回自己
private:
static AH_LOG* singleInstance; // 声明一个静态类
};
".cpp"
#include "AH_log.hpp"
#include <iostream>
#include <string>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
AH_LOG* AH_LOG::singleInstance = new AH_LOG();
AH_LOG &AH_LOG::printS(const char *fmt, ...){
char log[500] = {0};
va_list args;
va_start(args, fmt);
vsnprintf(log, sizeof(log) - 1, fmt, args);
va_end(args);
std::cout << log;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
return *this;
}
AH_LOG &AH_LOG::printTitle(const char *funcName, const char *type)
{
std::cout << "[" << type << "] @" << funcName << " ";
return *this;
}
AH_LOG &AH_LOG::getinstance(){
return *singleInstance;
}
总的来说就是定义一个返回自己的打印 log 头信息的函数,返回自己后再调用其自定义的PrintS 函数。 大家可以发挥创意,根据需要自己设计自己的LOG 输出函数。
后面会有完整例程。
二、使用宏定义(__VA_ARGS__
)输出log
这个特性是可以C 和 C++ 通用的。 如下:
#define LOG(...) printf(__VA_ARGS__)
这样子 我们使用 LOG("hello");
就相当于 printf("hello");
了
示例如下:
".h"
#define UGPRINT(...) printS(__VA_ARGS__)
#define UGINFO(...) printLogS(__func__, " info", __VA_ARGS__)
#define UGDEBUG(...) printLogS(__func__, "debug", __VA_ARGS__)
#define UGERROR(...) printLogS(__func__, "error", __VA_ARGS__)
void printS(const char *fmt, ...);
void printLogS(const char* funcname,const char* type, const char *fmt, ...);
void ug_log_hal_print(const char *str);
/* C libs */
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
/* my libs */
#include "ug_log.h"
void printS(const char *fmt, ...){
char log[300] = {0};
va_list args;
va_start(args, fmt);
vsnprintf(log, sizeof(log) - 1, fmt, args);
va_end(args);
ug_log_hal_print(log);
// if(log[strlen(log)] != '\n')
// ug_log_hal_print("\n");
}
void printLogS(const char* funcname,const char* type, const char *fmt, ...){
char log[300] = {0};
va_list args;
va_start(args, fmt);
vsnprintf(log, sizeof(log) - 1, fmt, args);
va_end(args);
ug_log_hal_print("[");
ug_log_hal_print(type);
ug_log_hal_print("] @");
ug_log_hal_print(funcname);
ug_log_hal_print(" ");
ug_log_hal_print(log);
if(log[strlen(log)] != '\n')
ug_log_hal_print("\n");
}
__attribute__((weak)) void ug_log_hal_print(const char* str){
/* HAL Lib sample */
// uint32_t cnt = 0;
// while (str[cnt++] != '\0');
// HAL_UART_Transmit(&UART1_Handler, str, cnt-1, 500);
/* STD Lib sample */
// UartSendStr(USART1, str);
}
三、完整示例
1. C++ 类特性示例代码
.hpp
/*! @file AH_log.hpp
* @version 0.0.1
* @date April 07 2021
*
* @brief
* Print and out log info.
*
*/
#ifndef __AH_LOG_HPP_
#define __AH_LOG_HPP_
#include <string>
#include <fstream>
// store log file local
// #define LOG_LOCALL_STORE
#if defined(LOG_LOCALL_STORE)
extern std::ofstream g_logFile; // log file handle
#endif
namespace AH
{
#define AHINFO\
AH_LOG::getinstance().printTitle(__func__, "Info").printS
#define AHWARNING\
AH_LOG::getinstance().printTitle(__func__, "Warning").printS
#define AHERROR\
AH_LOG::getinstance().printTitle(__func__, "Error").printS
#define AHTIPS\
AH_LOG::getinstance().printTitle(__func__, "Tips").printS
#define AHACTION\
AH_LOG::getinstance().printTitle(__func__, "Action").printS
typedef enum AH_Log_Mode {
LOG_MODE_DEFAULT = 0,
LOG_MODE_SIMPLE,
LOG_MODE_COMPLEX,
LOG_MODE_STORE_LOCALLY
} AH_Log_Mode;
typedef enum AH_Log_Type {
LOG_TYPE_INFO = 0,
LOG_TYPE_WARNING,
LOG_TYPE_ACTION,
LOG_TYPE_TIPS,
LOG_TYPE_ERROR
} AH_Log_Type;
class AH_LOG{
AH_LOG();
~AH_LOG();
public:
AH_LOG &printS(const char *fmt, ...);
AH_LOG &printTitle(const char *funcName, const char *type);
static AH_LOG &getinstance(); // 返回自己
private:
tm *getSystemTime(void);
static AH_LOG* singleInstance; // 声明一个静态类
bool storeLocall = false;
time_t tt; // time for log output.
char fileName[255];
};
}; // namespace AH
#endif // !__AH_LOG_HPP_
.cpp
/*! @file AH_log.cpp
* @version 0.0.1
* @date April 07 2021
*
* @brief
* Print and out log info.
*
*/
#include "AH_log.hpp"
#include <iostream>
#include <string>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#if defined(LOG_LOCALL_STORE)
std::ofstream g_logFile; // log file handle
#endif
namespace AH
{
AH_LOG* AH_LOG::singleInstance = new AH_LOG();
AH_LOG::AH_LOG()
{
#if defined(LOG_LOCALL_STORE)
tm *time = getSystemTime();
// AHINFO("Current system time: %d-%02d-%02d %02d:%02d:%02d",
// time->tm_year + 1900,
// time->tm_mon + 1,
// time->tm_mday,
// time->tm_hour,
// time->tm_min,
// time->tm_sec);
// AHINFO("Create Log File.");
sprintf(fileName, "/home/dji/osdkDemo/Log--%d-%02d-%02d--%02d:%02d.txt",
time->tm_year + 1900,
time->tm_mon + 1,
time->tm_mday,
time->tm_hour,
time->tm_min);
g_logFile.open(fileName , std::ios::app);
if (g_logFile.is_open())
{
// AHINFO("open file success");
// logFile << "This is a line.\n";
// logFile << "This is another line.\n";
// g_logFile.close();
return;
}
exit(-1);
#endif
}
AH_LOG::~AH_LOG()
{
#if defined(LOG_LOCALL_STORE)
g_logFile.close();
#endif
}
/*
format for tm*
AHINFO("current Time:%d-%02d-%02d %02d:%02d:%02d",
time->tm_year + 1900,
time->tm_mon + 1,
time->tm_mday,
time->tm_hour,
time->tm_min,
time->tm_sec);
*/
tm* AH_LOG::getSystemTime(void)
{
time( &tt );
tt = tt + 8*3600; // transform the time zone
tm* t= gmtime( &tt );
return t;
}
AH_LOG &AH_LOG::printS(const char *fmt, ...){
char log[500] = {0};
va_list args;
va_start(args, fmt);
vsnprintf(log, sizeof(log) - 1, fmt, args);
va_end(args);
std::cout << log;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
#if defined(LOG_LOCALL_STORE)
g_logFile << log << "\n";
g_logFile.flush();
#endif
return *this;
}
AH_LOG &AH_LOG::printTitle(const char *funcName, const char *type){
#if defined(LOG_LOCALL_STORE)
char timeStamp[255] = "hello";
tm *time = getSystemTime();
sprintf(timeStamp, "%02d:%02d:%02d || ",
time->tm_hour,
time->tm_min,
time->tm_sec);
// g_logFile.open(fileName , std::ios::app);
g_logFile << timeStamp << "[" << type << "] @" << funcName << " ";
// g_logFile.close();
#endif
std::cout << "[" << type << "] @" << funcName << " ";
return *this;
}
AH_LOG &AH_LOG::getinstance(){
return *singleInstance;
}
void printLog(const char *funcName, const char *log, const char *type, AH_Log_Mode mode){
std::string log_type;
log_type = type;
switch (mode)
{
case LOG_MODE_DEFAULT:
std::cout << "@" << funcName << " [" + log_type + "] " + log;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
break;
case LOG_MODE_SIMPLE:
std::cout << "@" << funcName << "[" + log_type + "] =>|| " + log ;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
break;
case LOG_MODE_STORE_LOCALLY:
std::cout << "@" << funcName << "[" + log_type + "] =>|| " + log;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
//TODO Store log locally.
break;
case LOG_MODE_COMPLEX:
std::cout << "============ " << "@" << funcName << " [" + log_type + "] ============ \n";
std::cout << log;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
std::cout << "====================================== \n";
break;
default:
break;
}
}
void printLog(const char *log, const char *type, AH_Log_Mode mode){
std::string log_type;
log_type = type;
switch (mode)
{
case LOG_MODE_DEFAULT:
std::cout << "[" + log_type + "] " + log;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
break;
case LOG_MODE_SIMPLE:
std::cout << "[" + log_type + "] =>|| " + log ;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
break;
case LOG_MODE_STORE_LOCALLY:
std::cout << "[" + log_type + "] =>|| " + log;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
//TODO Store log locally.
break;
case LOG_MODE_COMPLEX:
std::cout << "============== [" + log_type + "] ============== \n";
std::cout << log;
if(log[strlen(log)] != '\n')
std::cout << std::endl;
std::cout << "====================================== \n";
break;
default:
break;
}
}
}; // namespace AH
2. __VA_ARGS__
特性示例代码
.h
/*! @file ug_log.h
* @version 0.0.1
* @date May 12 2021
*
* @brief
* Print and out log info.
*
*/
#ifndef __UG_LOG_H
#define __UG_LOG_H
#define UGPRINT(...) printS(__VA_ARGS__)
#define UGINFO(...) printLogS(__func__, " info", __VA_ARGS__)
#define UGDEBUG(...) printLogS(__func__, "debug", __VA_ARGS__)
#define UGERROR(...) printLogS(__func__, "error", __VA_ARGS__)
void printS(const char *fmt, ...);
void printLogS(const char* funcname,const char* type, const char *fmt, ...);
void ug_log_hal_print(const char *str);
#endif // !__UG_LOG_H
.c
/*! @file ug_log.c
* @version 0.0.1
* @date May 12 2021
*
* @brief
* Print and out log info.
*
*/
/* C libs */
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
/* my libs */
#include "ug_log.h"
// #include "usart.h"
void printS(const char *fmt, ...){
char log[300] = {0};
va_list args;
va_start(args, fmt);
vsnprintf(log, sizeof(log) - 1, fmt, args);
va_end(args);
ug_log_hal_print(log);
// if(log[strlen(log)] != '\n')
// ug_log_hal_print("\n");
}
void printLogS(const char* funcname,const char* type, const char *fmt, ...){
char log[300] = {0};
va_list args;
va_start(args, fmt);
vsnprintf(log, sizeof(log) - 1, fmt, args);
va_end(args);
ug_log_hal_print("[");
ug_log_hal_print(type);
ug_log_hal_print("] @");
ug_log_hal_print(funcname);
ug_log_hal_print(" ");
ug_log_hal_print(log);
if(log[strlen(log)] != '\n')
ug_log_hal_print("\n");
}
__attribute__((weak)) void ug_log_hal_print(const char* str){
/* HAL Lib sample */
// uint32_t cnt = 0;
// while (str[cnt++] != '\0');
// HAL_UART_Transmit(&UART1_Handler, str, cnt-1, 500);
/* STD Lib sample */
// UartSendStr(USART1, str);
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!