Oui, vous pouvez le faire, mais c'est un peu moche et vous devez connaître le nombre maximal d'arguments. De plus si vous êtes sur une architecture où les arguments ne sont pas passés sur la pile comme le x86 (par exemple, PowerPC), vous devrez savoir si des types "spéciaux" (double, floats, altivec etc.) sont utilisés et si alors, traitez-les en conséquence. Cela peut être pénible rapidement mais si vous êtes sur x86 ou si la fonction d'origine a un périmètre bien défini et limité, cela peut fonctionner.
Ce sera toujours un hack , utilisez-le à des fins de débogage. Ne construisez pas votre logiciel autour de cela. Quoi qu'il en soit, voici un exemple de travail sur 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;
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;
}
Pour une raison quelconque, vous ne pouvez pas utiliser de flottants avec va_arg, gcc dit qu'ils sont convertis en double mais le programme plante. Cela seul démontre que cette solution est un hack et qu'il n'y a pas de solution générale. Dans mon exemple, j'ai supposé que le nombre maximum d'arguments était de 8, mais vous pouvez augmenter ce nombre. La fonction encapsulée n'utilisait également que des entiers, mais elle fonctionne de la même manière avec d'autres paramètres «normaux» puisqu'ils sont toujours convertis en entiers. La fonction cible connaîtra leurs types mais votre wrapper intermédiaire n'en a pas besoin. L'encapsuleur n'a pas non plus besoin de connaître le bon nombre d'arguments puisque la fonction cible le saura également. Pour faire un travail utile (sauf simplement enregistrer l'appel), vous devrez probablement connaître les deux.