2

Before you say it's duplicated, I already read this: How to pass variable number of arguments from one function to another?

I have a function like this:

void tlog_function(t_log* logger, const char* message_template, ...) {
    pthread_mutex_lock(&loggerLock);
    log_function(logger, message_template, ...); // What I want to do..
    pthread_mutex_unlock(&loggerLock);
}

And another function like this, which is not mine, I use it from a third-party library:

void log_function(t_log* logger, const char* message_template, ...);

As you can see, what I want to do is just add a mutex to this function to make it thread-safe, I know I can use va_list but in this case I cannot change the code of the second function, because it is inside a library and I only have the .h file.

So, is there any way to achieve this?

Community
  • 1
  • 1
Pablo Matias Gomez
  • 6,614
  • 7
  • 38
  • 72

2 Answers2

6

If you cannot change the code and there is no va_list version of the library function you can use the closest thing I am aware of is to use a macro and ##__VA_ARGS__ (which is a GCC only extension).

You will want something like this:

#define tlog_function(logger, message_template, ...) do { \
    pthread_mutex_lock(&loggerLock);                                         \
    log_function(logger, message_template, ##__VA_ARGS__);                   \
    pthread_mutex_unlock(&loggerLock);                                       \
} while(0)
Community
  • 1
  • 1
missimer
  • 4,022
  • 1
  • 19
  • 33
  • 1
    FYI, it's only the `, ## __VA_ARGS__` construct to permit passing *zero* variable arguments that is a GCC extension. `__VA_ARGS__` itself is standard C99. – zwol Jun 29 '15 at 20:21
  • @zwol thanks for the catch I have updated my answer to be more specific. – missimer Jun 29 '15 at 20:24
  • It worked! I just removed the types of the first two arguments as they are not needed and also there can't be a pointer. Thanks !! – Pablo Matias Gomez Jun 29 '15 at 20:31
  • @PabloMatíasGomez thanks for that catch about the types and I'm glad it worked. – missimer Jun 29 '15 at 20:32
  • @esm Also, why do you use `do while`? I just removed that and worked fine ! Is there any reason? – Pablo Matias Gomez Jun 29 '15 at 20:37
  • 1
    @PabloMatíasGomez It's a common trick to allow you to use your macro with if. See http://stackoverflow.com/questions/154136/do-while-and-if-else-statements-in-c-c-macros and http://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for – missimer Jun 29 '15 at 20:40
2

You cannot write a function that forwards its variable argument list to another variadic function with the facilities provided by standard C. Indeed, vfprintf exists precisely because this is not possible. (As discussed in esm's answer, a macro can do this.)

If additional third-party libraries are an option, libffi may be persuadable to do what you want. (How does libffi work, you ask? Hand-written assembly language.)

zwol
  • 135,547
  • 38
  • 252
  • 361