Так, ви можете це зробити, але це трохи негарно, і ви повинні знати максимальну кількість аргументів. Крім того, якщо ви перебуваєте в архітектурі, де аргументи не передаються на стек, як x86 (наприклад, PowerPC), вам доведеться знати, чи використовуються "спеціальні" типи (double, floats, altivec тощо) і якщо тож, розбирайтеся з ними відповідно. Це може бути боляче швидко, але якщо ви перебуваєте на x86 або якщо в оригінальній функції є чітко визначений і обмежений периметр, це може працювати.
Це все ще буде злом , використовуйте його для налагодження. Не будуйте програмного забезпечення навколо цього. У всякому разі, ось робочий приклад для 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;
}
Чомусь не можна використовувати floats з va_arg, gcc каже, що вони перетворюються в подвійний, але програма виходить з ладу. Це одне лише демонструє, що це рішення є хак і що загального рішення немає. У своєму прикладі я припускав, що максимальна кількість аргументів була 8, але ви можете збільшити це число. Обгорнута функція також використовувала лише цілі числа, але вона працює аналогічно з іншими 'нормальними' параметрами, оскільки вони завжди передаються цілим числам. Цільова функція буде знати їх типи, але вашому посереднику не потрібно. Обгортці також не потрібно знати потрібну кількість аргументів, оскільки цільова функція також знатиме це. Щоб виконувати корисну роботу (за винятком лише реєстрації дзвінка), вам, мабуть, доведеться знати обоє.