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