Да, вы можете сделать это, но это несколько уродливо, и вы должны знать максимальное количество аргументов. Более того, если вы используете архитектуру, в которой аргументы не передаются в стек, например, 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, но вы можете увеличить это число. Обернутая функция также использует только целые числа, но она работает так же, как и другие «нормальные» параметры, поскольку они всегда приводятся к целым числам. Целевая функция будет знать их типы, но ваша промежуточная оболочка не обязана. Оболочке также не нужно знать правильное количество аргументов, поскольку целевая функция также будет знать это. Чтобы сделать полезную работу (кроме простой регистрации звонка), вам, вероятно, придется знать и то и другое.