Да, вы можете сделать это, но это несколько уродливо, и вы должны знать максимальное количество аргументов. Более того, если вы работаете в архитектуре, в которой аргументы не передаются в стек, например, в x86 (например, PowerPC), вам необходимо знать, используются ли «специальные» типы (double, float, 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;
}
По какой-то причине вы не можете использовать float с va_arg, gcc говорит, что они конвертируются в удвоенные, но программа вылетает. Уже одно это демонстрирует, что это решение является взломом и что нет общего решения.
В моем примере я предположил, что максимальное количество аргументов было 8, но вы можете увеличить это число. Обернутая функция также использует только целые числа, но она работает так же, как и другие «нормальные» параметры, поскольку они всегда приводятся к целым числам. Функция назначения будет знать их типы, но ваша промежуточная оболочка не нуждается в этом. Оболочке также не нужно знать правильное количество аргументов, поскольку целевая функция также будет знать это.
Чтобы сделать полезную работу (кроме простой регистрации звонка), вам, вероятно, придется знать и то и другое.