Sì, puoi farlo, ma è un po 'brutto e devi conoscere il numero massimo di argomenti. Inoltre, se utilizzi un'architettura in cui gli argomenti non vengono passati nello stack come x86 (ad esempio, PowerPC), dovrai sapere se vengono utilizzati tipi "speciali" (double, float, altivec ecc.) E se quindi, affrontali di conseguenza. Può essere doloroso rapidamente ma se sei su x86 o se la funzione originale ha un perimetro ben definito e limitato, può funzionare.
Sarà comunque un hack , usalo a scopo di debug. Non creare software attorno a quello. Ad ogni modo, ecco un esempio funzionante su x86:
#include <stdio.h>
#include <stdarg.h>
int old_variadic_function(int n, ...)
{
va_list args;
int i = 0;
va_start(args, n);
if(i++<n) printf("arg %d is 0x%x\n", i, va_arg(args, int));
if(i++<n) printf("arg %d is %g\n", i, va_arg(args, double));
if(i++<n) printf("arg %d is %g\n", i, va_arg(args, double));
va_end(args);
return n;
}
int old_variadic_function_wrapper(int n, ...)
{
va_list args;
int a1;
int a2;
int a3;
int a4;
int a5;
int a6;
int a7;
int a8;
/* Do some work, possibly with another va_list to access arguments */
/* Work done */
va_start(args, n);
a1 = va_arg(args, int);
a2 = va_arg(args, int);
a3 = va_arg(args, int);
a4 = va_arg(args, int);
a5 = va_arg(args, int);
a6 = va_arg(args, int);
a7 = va_arg(args, int);
va_end(args);
return old_variadic_function(n, a1, a2, a3, a4, a5, a6, a7, a8);
}
int main(void)
{
printf("Call 1: 1, 0x123\n");
old_variadic_function(1, 0x123);
printf("Call 2: 2, 0x456, 1.234\n");
old_variadic_function(2, 0x456, 1.234);
printf("Call 3: 3, 0x456, 4.456, 7.789\n");
old_variadic_function(3, 0x456, 4.456, 7.789);
printf("Wrapped call 1: 1, 0x123\n");
old_variadic_function_wrapper(1, 0x123);
printf("Wrapped call 2: 2, 0x456, 1.234\n");
old_variadic_function_wrapper(2, 0x456, 1.234);
printf("Wrapped call 3: 3, 0x456, 4.456, 7.789\n");
old_variadic_function_wrapper(3, 0x456, 4.456, 7.789);
return 0;
}
Per qualche motivo, non puoi usare float con va_arg, gcc dice che sono convertiti in double ma il programma si arresta in modo anomalo. Questo da solo dimostra che questa soluzione è un hack e che non esiste una soluzione generale. Nel mio esempio ho assunto che il numero massimo di argomenti fosse 8, ma è possibile aumentare quel numero. La funzione wrapping utilizzava anche solo numeri interi, ma funziona allo stesso modo con altri parametri "normali" poiché eseguono sempre il cast su numeri interi. La funzione target conoscerà i loro tipi, ma il wrapper intermedio non è necessario. Inoltre, il wrapper non ha bisogno di conoscere il giusto numero di argomenti poiché anche la funzione target lo saprà. Per fare un lavoro utile (tranne per il semplice logging della chiamata), probabilmente dovrete conoscere entrambi.