log配置信息:
/*================
* Log settings
*===============*/
/*================
* 日志设置
*===============*/
/*1: Enable the log module*/
/*1: 启用日志模块*/
#define LV_USE_LOG 1
#if LV_USE_LOG
/* How important log should be added:
* LV_LOG_LEVEL_TRACE A lot of logs to give detailed information 跟踪大量日志以提供详细信息
* LV_LOG_LEVEL_INFO Log important events 重要事件
* LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem如果发生了不想要发生的事情但没有引起错误,请记录
* LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail 只有在系统可能出现故障时才会出现的严重问题
* LV_LOG_LEVEL_NONE Do not log anything不要记录任何内容
*/
# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
/* 1: Print the log with 'printf'; 用“printf”打印日志
* 0: user need to register a callback with `lv_log_register_print_cb` 用户需要使用注册回调 */
# define LV_LOG_PRINTF 1
#endif /*LV_USE_LOG*/
/* Export integer constant to binding.导出整型常量绑定。
* This macro is used with constants in the form of LV_<CONST> that 此宏与LV_<CONST>形式的常量一起使用:
* should also appear on lvgl binding API such as Micropython也应该出现在lvgl绑定的API上,比如Micropython
*
* The default value just prevents a GCC warning.默认值只是防止GCC警告。
*/
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning
lv_log.h
/**
* @file lv_log.h
*
*/
#ifndef LV_LOG_H
#define LV_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include <stdint.h>
/*********************
* DEFINES
*********************/
/*Possible log level. For compatibility declare it independently from `LV_USE_LOG`*/
/*日志级别. 为了兼容性,请独立声明'LV_USE_LOG' */
#define LV_LOG_LEVEL_TRACE 0 /**< A lot of logs to give detailed information 提供大量详细信息的日志*/
#define LV_LOG_LEVEL_INFO 1 /**< Log important events 记录重要事件*/
#define LV_LOG_LEVEL_WARN 2 /**< Log if something unwanted happened but didn't caused problem 如果发生了意外但没有引起问题,请记录*/
#define LV_LOG_LEVEL_ERROR 3 /**< Only critical issue, when the system may fail 仅系统崩溃时出现的严重问题*/
#define LV_LOG_LEVEL_USER 4 /**< Custom logs from the user 来自用户的自定义日志*/
#define LV_LOG_LEVEL_NONE 5 /**< Do not log anything 不要记录任何内容*/
#define _LV_LOG_LEVEL_NUM 6 /**< Number of log levels 日志级别数*/
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_TRACE);
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_INFO);
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_WARN);
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_ERROR);
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_USER);
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_NONE);
typedef int8_t lv_log_level_t;
#if LV_USE_LOG
/**********************
* TYPEDEFS
**********************/
/**
* Log print function. Receives "Log Level", "File path", "Line number", "Function name" and "Description".
* 日志打印。 接收 "日志级别"、 "文件路径"、 "行号" 、"函数名"和"说明"。
*/
typedef void (*lv_log_print_g_cb_t)(lv_log_level_t level, const char *, uint32_t, const char *, const char *);
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Register custom print/write function to call when a log is added.
* It can format its "File path", "Line number" and "Description" as required
* and send the formatted log message to a console or serial port.
* @param print_cb a function pointer to print a log
* 注册自定义打印/写入函数以在添加日志时调用。
* 它可以根据需要格式化“文件路径”、“行号”和“说明”
* 并将格式化的日志消息发送到控制台或串行端口。
* @param print_cb打印日志的函数指针
*/
void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb);
/**
* Add a log
* @param level the level of log. (From `lv_log_level_t` enum)
* @param file name of the file when the log added
* @param line line number in the source code where the log added
* @param func name of the function when the log added
* @param format printf-like format string
* @param ... parameters for `format`
* 添加日志
* @param level日志级别 (From `lv_log_level_t` enum)
* @param file添加日志时的文件名
* @param line添加日志在源代码中的行号
* @param func添加日志时函数名
* @param format printf-like格式字符串
* @param ...`format`的参数
*/
void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * func, const char * format, ...);
/**********************
* MACROS
**********************/
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_TRACE
#define LV_LOG_TRACE(...) _lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
#define LV_LOG_TRACE(...) \
{ \
; \
}
#endif
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO
#define LV_LOG_INFO(...) _lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
#define LV_LOG_INFO(...) \
{ \
; \
}
#endif
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_WARN
#define LV_LOG_WARN(...) _lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
#define LV_LOG_WARN(...) \
{ \
; \
}
#endif
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_ERROR
#define LV_LOG_ERROR(...) _lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
#define LV_LOG_ERROR(...) \
{ \
; \
}
#endif
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_USER
#define LV_LOG_USER(...) _lv_log_add(LV_LOG_LEVEL_USER, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
#define LV_LOG_USER(...) \
{ \
; \
}
#endif
#else /*LV_USE_LOG*/
/*Do nothing if `LV_USE_LOG 0`*/
#define _lv_log_add(level, file, line, ...) \
{ \
; \
}
#define LV_LOG_TRACE(...) \
{ \
; \
}
#define LV_LOG_INFO(...) \
{ \
; \
}
#define LV_LOG_WARN(...) \
{ \
; \
}
#define LV_LOG_ERROR(...) \
{ \
; \
}
#define LV_LOG_USER(...) \
{ \
; \
}
#endif /*LV_USE_LOG*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_LOG_H*/
lv_log.c
/**
* @file lv_log.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_log.h"
#if LV_USE_LOG
#include <stdarg.h>
#include <string.h>
#include "lv_printf.h"
#if LV_LOG_PRINTF
#include <stdio.h>
#endif
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
static lv_log_print_g_cb_t custom_print_cb;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Register custom print/write function to call when a log is added.
* It can format its "File path", "Line number" and "Description" as required
* and send the formatted log message to a console or serial port.
* @param print_cb a function pointer to print a log
* 注册自定义打印/写入函数以在添加日志时调用。
* 它可以根据需要格式化“文件路径”、“行号”和“说明”
* 并将格式化的日志消息发送到控制台或串行端口。
* @param print_cb打印日志的函数指针
*/
void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb)
{
custom_print_cb = print_cb;//静态变量来承接
}
/**
* Add a log
* @param level the level of log. (From `lv_log_level_t` enum)
* @param file name of the file when the log added
* @param line line number in the source code where the log added
* @param func name of the function when the log added
* @param format printf-like format string
* @param ... parameters for `format`
* 添加日志
* @param level日志级别 (From `lv_log_level_t` enum)
* @param file添加日志时的文件名
* @param line添加日志在源代码中的行号
* @param func添加日志时函数名
* @param format printf-like格式字符串
* @param ...`format`的参数
*/
void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * func, const char * format, ...)
{
if(level >= _LV_LOG_LEVEL_NUM) return; /*Invalid level 无效级别*/
if(level >= LV_LOG_LEVEL) {
va_list args; // 申请参数列表变量
va_start(args, format); // 申明最后一个传递给函数的已知的固定参数
char buf[256]; // "说明""Description" 可以在lv_log.h注释中找到出处
lv_vsnprintf(buf, sizeof(buf), format, args); //猜测:将参数format... 结合放到buf中
va_end(args);
#if LV_LOG_PRINTF //用“printf”打印日志
/*Use only the file name not the path 只使用文件名而不是路径*/
size_t p;
for(p = strlen(file); p > 0; p--) {
if(file[p] == '/' || file[p] == '\\') {
p++; /*Skip the slash 跳过斜杠*/
break;
}
}
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error", "User"};
printf("%s: %s \t(%s #%d %s())\n", lvl_prefix[level], buf, &file[p], line, func); //打印日志
#else // `lv_log_register_print_cb` 用户需要使用注册回调
if(custom_print_cb) custom_print_cb(level, file, line, func, buf);
#endif
}
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_LOG*/
总结
log 可以从配置信息Log settings中找到相关的配置选项。
.h文件中:
有日志级别
#define LV_LOG_LEVEL_TRACE 0 /**< A lot of logs to give detailed information 提供大量详细信息的日志*/
#define LV_LOG_LEVEL_INFO 1 /**< Log important events 记录重要事件*/
#define LV_LOG_LEVEL_WARN 2 /**< Log if something unwanted happened but didn't caused problem 如果发生了意外但没有引起问题,请记录*/
#define LV_LOG_LEVEL_ERROR 3 /**< Only critical issue, when the system may fail 仅系统崩溃时出现的严重问题*/
#define LV_LOG_LEVEL_USER 4 /**< Custom logs from the user 来自用户的自定义日志*/
#define LV_LOG_LEVEL_NONE 5 /**< Do not log anything 不要记录任何内容*/
#define _LV_LOG_LEVEL_NUM 6 /**< Number of log levels 日志级别数*/
还有函数
void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb);
void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * func, const char * format, ...);
还有 宏
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_TRACE
#define LV_LOG_TRACE(...) _lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
#define LV_LOG_TRACE(...) \
{ \
; \
}
#endif
不明白的地方
1.防止GCC警告的用法
2. c的这个库 #include <stdarg.h>
3.源代码#include "lv_printf.h"
再看看这个函数怎么写的lv_vsnprintf(buf, sizeof(buf), format, args);