From 00e7e4154b8e77ebbdc2973fdf867a775fb61076 Mon Sep 17 00:00:00 2001 From: eutro Date: Thu, 30 Oct 2025 00:18:31 +0000 Subject: [PATCH] [rcore] Add non-va_list custom logging callback --- examples/Makefile | 1 + examples/core/core_custom_logging2.c | 89 ++++++++++++++++++++++++++++ src/raylib.h | 2 + src/utils.c | 19 +++++- 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 examples/core/core_custom_logging2.c diff --git a/examples/Makefile b/examples/Makefile index b5e968079..16a424ce8 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -527,6 +527,7 @@ CORE = \ core/core_clipboard_text \ core/core_custom_frame_control \ core/core_custom_logging \ + core/core_custom_logging2 \ core/core_delta_time \ core/core_directory_files \ core/core_drop_files \ diff --git a/examples/core/core_custom_logging2.c b/examples/core/core_custom_logging2.c new file mode 100644 index 000000000..8954cabf5 --- /dev/null +++ b/examples/core/core_custom_logging2.c @@ -0,0 +1,89 @@ +/******************************************************************************************* +* +* raylib [core] example - custom logging 2 +* +* Example complexity rating: [★★★☆] 3/4 +* +* Example originally created with raylib 5.5, last time updated with raylib 5.5 +* +* Example contributed by B. Szilvasy (@eutro) and reviewed by ??? +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2025 B. Szilvasy (@eutro) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include // Required for: fopen(), fclose(), fputc(), fwrite(), printf(), fprintf(), funopen() +#include // Required for: time_t, tm, time(), localtime(), strftime() + +// Custom logging function +void CustomLog(int msgType, const char *text) +{ + char timeStr[64] = { 0 }; + time_t now = time(NULL); + struct tm *tm_info = localtime(&now); + + strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", tm_info); + printf("[%s] ", timeStr); + + switch (msgType) + { + case LOG_INFO: printf("[INFO] : "); break; + case LOG_ERROR: printf("[ERROR]: "); break; + case LOG_WARNING: printf("[WARN] : "); break; + case LOG_DEBUG: printf("[DEBUG]: "); break; + default: break; + } + + printf("%s\n", text); +} + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + // Set custom logger + SetTraceLogCallback2(CustomLog); + + InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging"); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update your variables here + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText("Check out the console output to see the custom logger in action!", 60, 200, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/src/raylib.h b/src/raylib.h index e4be11084..7c253b9c0 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -951,6 +951,7 @@ typedef enum { // Callbacks to hook some internal functions // WARNING: These callbacks are intended for advanced users typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages +typedef void (*TraceLogCallback2)(int logLevel, const char *text); // Logging: Redirect trace log messages 2 typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data @@ -1111,6 +1112,7 @@ RLAPI void MemFree(void *ptr); // Internal me // Set custom callbacks // WARNING: Callbacks setup is intended for advanced users RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log +RLAPI void SetTraceLogCallback2(TraceLogCallback2 callback); // Set custom trace log 2 RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader diff --git a/src/utils.c b/src/utils.c index 123c7b0b9..b5aa900f7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -62,6 +62,7 @@ static int logTypeLevel = LOG_INFO; // Minimum log type level static TraceLogCallback traceLog = NULL; // TraceLog callback function pointer +static TraceLogCallback2 traceLog2 = NULL; // TraceLog callback function pointer 2 static LoadFileDataCallback loadFileData = NULL; // LoadFileData callback function pointer static SaveFileDataCallback saveFileData = NULL; // SaveFileText callback function pointer static LoadFileTextCallback loadFileText = NULL; // LoadFileText callback function pointer @@ -70,7 +71,8 @@ static SaveFileTextCallback saveFileText = NULL; // SaveFileText callback fun //---------------------------------------------------------------------------------- // Functions to set internal callbacks //---------------------------------------------------------------------------------- -void SetTraceLogCallback(TraceLogCallback callback) { traceLog = callback; } // Set custom trace log +void SetTraceLogCallback(TraceLogCallback callback) { traceLog = callback; traceLog2 = NULL; } // Set custom trace log +void SetTraceLogCallback2(TraceLogCallback2 callback) { traceLog2 = callback; traceLog = NULL; } // Set custom trace log void SetLoadFileDataCallback(LoadFileDataCallback callback) { loadFileData = callback; } // Set custom file data loader void SetSaveFileDataCallback(SaveFileDataCallback callback) { saveFileData = callback; } // Set custom file data saver void SetLoadFileTextCallback(LoadFileTextCallback callback) { loadFileText = callback; } // Set custom file text loader @@ -116,6 +118,21 @@ void TraceLog(int logType, const char *text, ...) va_end(args); return; } + else if (traceLog2) + { + // Does NOT include null terminator. + int requiredByteCount = vsnprintf(NULL, 0, text, args); + va_end(args); + // Error from vsnprintf() + if (requiredByteCount < 0) return; + char *buffer = RL_CALLOC(requiredByteCount + 1, sizeof(char)); + va_start(args, text); + vsnprintf(buffer, requiredByteCount + 1, text, args); + va_end(args); + traceLog2(logType, buffer); + RL_FREE(buffer); + return; + } #if defined(PLATFORM_ANDROID) switch (logType)