はい、できますが、やや醜く、引数の最大数を知る必要があります。さらに、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 は double に変換されると言いますが、プログラムはクラッシュします。それだけでも、このソリューションがハックであり、一般的なソリューションがないことを示しています。この例では、引数の最大数は 8 であると仮定しましたが、その数を増やすことができます。ラップされた関数も整数のみを使用しましたが、他の「通常の」パラメーターは常に整数にキャストされるため、同じように機能します。ターゲット関数はそれらの型を認識しますが、中間ラッパーはその必要はありません。ターゲット関数もそれを知っているので、ラッパーも正しい数の引数を知る必要はありません。有用な作業を行うには (呼び出しをログに記録することを除く)、おそらく両方を知っている必要があります。