Sim, você pode fazê-lo, mas é um pouco feio e você precisa saber o número máximo de argumentos. Além disso, se você estiver em uma arquitetura em que os argumentos não sejam passados na pilha como o x86 (por exemplo, PowerPC), será necessário saber se tipos "especiais" (double, floats, altivec etc.) são usados e se então, lide com eles de acordo. Pode ser doloroso rapidamente, mas se você estiver no x86 ou se a função original tiver um perímetro bem definido e limitado, ela poderá funcionar.
Ainda será um hack , use-o para fins de depuração. Não crie seu software em torno disso. De qualquer forma, aqui está um exemplo de trabalho no 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;
}
Por alguma razão, você não pode usar carros alegóricos com va_arg, o gcc diz que eles são convertidos para o dobro, mas o programa trava. Isso por si só demonstra que esta solução é um hack e que não há uma solução geral. No meu exemplo, assumi que o número máximo de argumentos era 8, mas você pode aumentar esse número. A função empacotada também usou apenas números inteiros, mas funciona da mesma maneira com outros parâmetros 'normais', pois eles sempre são convertidos em números inteiros. A função de destino conhecerá seus tipos, mas seu invólucro intermediário não precisa. O wrapper também não precisa saber o número certo de argumentos, pois a função de destino também o conhecerá. Para fazer um trabalho útil (exceto apenas registrar a chamada), você provavelmente precisará conhecer as duas coisas.