Otus
Otus

Reputation: 345

How to redefine print function at runtime in C

I'm currently using a simple preprocessor switch to disable/enable my debug statements. I have printf retargeted to the UART output, and then define my print function in a globally included header (globals.h) to make it easy to disable all debugging like this:

#ifdef USE_UART
   #define MY_PRINT(...) printf(__VA_ARGS__)
#else
   #define MY_PRINT(...) 
#endif

All my application files can then print debug messages over UART like this:

MY_PRINT("\t<<Battery Voltage: %d>>\r\n", vBat);

What I'm trying to do is have this be switched by external input (ie a button press) during run time. For example something like this:

void my_print(const char * pString){
    if (uart_mode == UART_ON){
        printf(pString);
    }
}

Where uart_mode could be toggled via the external input. I'm having trouble figuring out how to pass variable arguements properly into printf through this function. Is this possible? Is there a better way to do it?

Upvotes: 1

Views: 6643

Answers (3)

nategoose
nategoose

Reputation: 12392

As David Schwartz said, that's what vprintf is for.

#include <stdarg.h>
void my_print(const char * pString, ...){
    va_list args;
    va_start(args, pString);
    if (uart_mode == UART_ON){
        vprintf(pString, args);
    }
    va_end(args);
}

Upvotes: 3

ShadowRanger
ShadowRanger

Reputation: 155684

A decent approach that avoids conditionals at runtime (though it's still dynamic dispatch) and mimics function calls precisely (because it is a function call) would be:

typedef int (*printf_func_t)(const char *, ...);

int dummy_printf(const char *format, ...) {
    return 0;
}

/* Set initial value based on initial uart_mode */
printf_func_t dynamic_printf = uart_mode == UART_ON ? &printf : &dummy_printf;

In some other toggle code (where uart_mode is changed), you'd just test and reassign:

dynamic_printf = uart_mode == UART_ON ? &printf : &dummy_printf;

Actual users then always call dynamic_printf in place of printf, and it calls whichever function is currently assigned to the function pointer. No read or test of uart_mode occurs when printing, it just calls whatever function is found at the time.

Upvotes: 4

David Schwartz
David Schwartz

Reputation: 182885

How about something like this:

#define MY_PRINT(...)                       \
    do {                                    \
         if (uart_mode == UART_ON)          \
             printf(__VA_ARGS__);           \
    } while(0)

Upvotes: 3

Related Questions