需要注释掉原有的 av_log
声明和实现,然后将新代码添加到 log.h
中。以下是完整、优化的实现方案:
在log.h中添加一下代码,已定义新的av_log函数。
c
// log.h
#include <stdio.h>
// 修改函数签名,增加 file 和 line 参数
static void av_log_impl(void* avcl, int level, const char *file, int line, const char *fmt, ...) {
va_list vl;
va_start(vl, fmt);
// 动态拼接调用位置信息(避免缓冲区溢出)
char new_fmt[1024];
snprintf(new_fmt, sizeof(new_fmt), "[%s:%d] %s", file, line, fmt);
av_vlog(avcl, level, new_fmt, vl); // 调用底层日志函数
va_end(vl);
}
// 定义包装宏:在调用点展开 __FILE__ 和 __LINE__
#define av_log(avcl, level, fmt, ...) \
av_log_impl(avcl, level, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
需要同时进行的修改:
-
在实现文件中注释掉原有函数定义 :
在你的实现文件(如 log.c)中找到原函数并注释掉:
c// void av_log(void* avcl, int level, const char *fmt, ...) // { // ... 原有实现 ... // }
-
注释掉原来的av_log声明 :
在 log.h 中,注释掉原来的av_log声明:
c// 注释掉原来的av_log声明 // void av_log(void* avcl, int level, const char *fmt, ...);
-
确保 av_vlog 可用 :
确保在 log.h 中声明了
av_vlog
函数:cvoid av_vlog(void* avcl, int level, const char *fmt, va_list vl);
关键优化说明:
-
安全缓冲区:
- 使用固定大小缓冲区避免动态内存分配
- 安全截断确保不会越界 (snprintf 的自动截断特性)
-
性能考虑:
static
函数定义避免符号冲突- 内联调用位置信息仅在启用日志时才处理
-
编译器兼容性:
##__VA_ARGS__
处理 GNU C/C++ 的空参数情况- 使用标准 C99 特性保证可移植性
-
日志格式灵活性 :
如果想添加更多上下文(如函数名),可扩展为:
c#define av_log(avcl, level, fmt, ...) \ av_log_impl(avcl, level, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__)
然后在函数中修改格式字符串为
"[%s:%d] %s: %s"
这样修改后,所有调用
av_log
的地方都会自动添加准确的位置信息,例如:
cav_log(NULL, 1, "Starting playback"); // 输出格式: [player.c:42] Starting playback