Tak, możesz to zrobić, ale jest to trochę brzydkie i musisz znać maksymalną liczbę argumentów. Ponadto, jeśli masz architekturę, w której argumenty nie są przekazywane na stosie, takie jak x86 (na przykład PowerPC), będziesz musiał wiedzieć, czy są używane typy „specjalne” (podwójne, zmiennoprzecinkowe, altivec itp.) I czy więc radzcie sobie z nimi odpowiednio. Może to być szybko bolesne, ale jeśli używasz x86 lub jeśli oryginalna funkcja ma dobrze zdefiniowany i ograniczony obwód, może działać.
To nadal będzie hack , użyj go do celów debugowania. Nie buduj wokół tego oprogramowania. Tak czy inaczej, oto działający przykład na 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;
}
Z jakiegoś powodu nie można używać liczb zmiennoprzecinkowych z va_arg, gcc mówi, że są one konwertowane na podwójne, ale program ulega awarii. Samo to pokazuje, że to rozwiązanie jest włamaniem i że nie ma ogólnego rozwiązania. W moim przykładzie założyłem, że maksymalna liczba argumentów wynosiła 8, ale można zwiększyć tę liczbę. Funkcja zawinięcia również używała tylko liczb całkowitych, ale działa tak samo z innymi „normalnymi” parametrami, ponieważ zawsze rzutują na liczby całkowite. Funkcja docelowa zna ich typy, ale opakowanie pośrednie nie musi tego robić. Opakowanie również nie musi znać odpowiedniej liczby argumentów, ponieważ funkcja docelowa również to zna. Aby wykonać przydatną pracę (oprócz rejestrowania połączenia), prawdopodobnie będziesz musiał znać oba.