Sí, puedes hacerlo, pero es algo feo y tienes que saber la cantidad máxima de argumentos. Además, si está en una arquitectura donde los argumentos no se pasan en la pila como el x86 (por ejemplo, PowerPC), tendrá que saber si se usan tipos "especiales" (doble, flotantes, altivec, etc.) y si entonces, trate con ellos en consecuencia. Puede ser doloroso rápidamente, pero si está en x86 o si la función original tiene un perímetro bien definido y limitado, puede funcionar.
Todavía será un hack , úsalo para propósitos de depuración. No construyas tu software alrededor de eso. De todos modos, aquí hay un ejemplo de trabajo en 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 alguna razón, no puede usar flotantes con va_arg, gcc dice que se convierten a doble pero el programa falla. Eso por sí solo demuestra que esta solución es un truco y que no hay una solución general. En mi ejemplo supuse que el número máximo de argumentos era 8, pero puede aumentar ese número. La función envuelta también solo usaba enteros, pero funciona de la misma manera con otros parámetros 'normales' ya que siempre se convierten a enteros. La función de destino conocerá sus tipos, pero su envoltorio intermediario no necesita saberlo. El contenedor tampoco necesita saber el número correcto de argumentos ya que la función de destino también lo sabrá. Sin embargo, para hacer un trabajo útil (excepto solo registrar la llamada), probablemente tenga que saber ambos.