应用日志:printf + valist
cmake_minimum_required(VERSION 3.14)
project(app_logger CXX)
set(CMAKE_CXX_STANDARD 17)
add_executable(app_logger_demo app_logger_demo.cpp)
#pragma once
#include <cstdarg>
#include <cstdio>
#include <string>
namespace demo {
enum class Level {
Debug = 0,
Info,
Warn,
Error
};
inline const char* level_name(Level level) {
switch (level) {
case Level::Debug:
return "DEBUG";
case Level::Info:
return "INFO";
case Level::Warn:
return "WARN";
case Level::Error:
return "ERROR";
}
return "UNKNOWN";
}
inline void logf(Level level, const char* file, int line, const char* fmt, ...) {
std::printf("[%s] %s:%d - ", level_name(level), file, line);
va_list args;
va_start(args, fmt);
std::vprintf(fmt, args);
va_end(args);
std::printf("\n");
}
inline void logf_manual(Level level, const char* file, int line, const char* fmt, ...) {
std::printf("[%s] %s:%d - ", level_name(level), file, line);
va_list args;
va_start(args, fmt);
const char* str_arg = va_arg(args, const char*);
int int_arg = va_arg(args, int);
std::printf(fmt, str_arg, int_arg);
va_end(args);
std::printf("\n");
}
#define APP_LOG_INFO(fmt, ...) demo::logf(demo::Level::Info, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define APP_LOG_MANUAL(fmt, ...) demo::logf_manual(demo::Level::Info, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
}
#include "app_logger.h"
int main() {
using namespace demo;
const char* user = "Alice";
int score = 23;
APP_LOG_INFO("1. User %s has score %d", user, score);
APP_LOG_MANUAL("2. User %s has score %d", user, score);
return 0;
}
SDK 回调日志
cmake_minimum_required(VERSION 3.14)
project(sdk_logger CXX)
set(CMAKE_CXX_STANDARD 17)
add_library(fake_sdk sdk_log.cpp)
add_executable(sdk_callback_demo sdk_callback_demo.cpp)
target_link_libraries(sdk_callback_demo PRIVATE fake_sdk)
#pragma once
#include <cstddef>
extern "C" {
typedef enum {
SDK_LOG_DEBUG = 0,
SDK_LOG_INFO = 1,
SDK_LOG_WARN = 2,
SDK_LOG_ERROR = 3,
} sdk_log_level_t;
typedef void (*sdk_log_callback_t) (
sdk_log_level_t level,
const char* filename,
int line,
const char* message
);
void sdk_register_log_callback(sdk_log_callback_t cb);
void sdk_do_something(int task_id);
}
#include "sdk_log.h"
#include <cstdio>
#include <cstdarg>
#include <string>
#include <mutex>
namespace {
sdk_log_callback_t g_cb = nullptr;
std::mutex g_mu;
void sdk_log_fire(sdk_log_level_t lv, const char* file, int line , const char* fmt, ...) {
if (!g_cb) return ;
char buf[256];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
g_cb(lv, file, line, buf);
}
}
#define SDK_LOG_INFO_IMPL(fmt, ...) sdk_log_fire(SDK_LOG_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define SDK_LOG_ERROR_IMPL(fmt, ...) sdk_log_fire(SDK_LOG_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
extern "C" {
void sdk_register_log_callback(sdk_log_callback_t cb) {
std::lock_guard<std::mutex> lk(g_mu);
g_cb = cb;
}
void sdk_do_something(int task_id) {
SDK_LOG_INFO_IMPL("Starting task %d", task_id);
if (task_id < 0) {
SDK_LOG_ERROR_IMPL("Invalid task if: %d", task_id);
return ;
}
SDK_LOG_INFO_IMPL("Task %d done", task_id);
}
}
#include "sdk_log.h"
#include <cstdio>
void my_log_callback(sdk_log_level_t level,
const char* file,
int line,
const char* msg) {
const char* lvname = (level==SDK_LOG_INFO ? "INFO" :
level==SDK_LOG_ERROR ? "ERROR" : "OTHER");
std::printf("[%s] %s:%d - %s\n", lvname, file, line, msg);
}
int main() {
sdk_register_log_callback(&my_log_callback);
sdk_do_something(42);
sdk_do_something(-1);
return 0;
}