これが私がCで行ったことで、関数をラップアラウンドします。それがあなたを助け/刺激することを願っています。主な制限は、関数のシグネチャを変更する必要があるため、ユーザー定義関数のみをラップできることです。
私のソリューションはva_arg構造を使用しています。
#include <stdarg.h>
void * super_wrapper( void * (*fn)(), void * ret, int n, ...)
{
va_list = my_list;
va_start(my_list, n);
ret = (*fn)(ret, n, my_list);
va_end(my_list);
return ret
}
ラッパーの署名は、実行する関数へのポインター、戻り値を取得するために関数に与えるポインター、関数への呼び出しの引数の数、そして実行する関数の引数を取ります。電話。
va_listは引数のリストです。va_startで初期化します。va_startの最初の引数は、初期化するva_listです。2番目の引数は、現在の関数の最後の既知のパラメーターです(この例では、「n」です)。
ここで、ユーザー定義関数の省略記号の代わりに、引数va_listを配置します。
私が持っていた2つの例:
double sum (int n, ...)
{
int i;
double res = 0;
double tmp;
va_list = my_list;
va_start(my_list, n);
for(i=0; i<n; i++)
{
tmp = va_arg(my_list, double);
res += tmp;
}
va_end(my_list);
return res;
}
void my_print(int n, ...)
{
int i;
va_list my_list;
va_start(my_list, n);
char * tmp;
for(i=0; i<n; i++)
{
tmp = va_arg(my_list, char *);
printf("%s ", tmp);
}
printf("\n");
va_end(my_list);
}
同じラッパーを使用して、署名と関数本体にいくつかの変更を加えて、この2つの異なる関数を呼び出すことができました。重要なのは、引数とリターンでは、ポインターのみを与えるということです。したがって、ポインタを逆参照する必要があります。
void * sum (void * ret, int n, va_list my_list)
{
int i;
double res = 0;
double *tmp;
for(i=0; i<n; i++)
{
tmp = va_arg(my_list, double);
res += *tmp;
}
ret = &res;
return ret;
}
void* my_print(int n, ...)
{
int i;
char ** tmp;
for(i=0; i<n; i++)
{
tmp = va_arg(my_list, char **);
printf("%s ", *tmp);
}
printf("\n");
return ret;
}
これで、メインで同じラッパー関数を使用して、次の2つの関数を呼び出すことができます。
void main()
{
double two = 2.0;
double three = 3.0;
double fifteen = 15.0;
char *I, *am, *a, *great, *wrapper;
I = malloc(sizeof(char) * 2);
am = malloc(sizeof(char) * 3);
a = malloc(sizeof(char)*2);
great = malloc(sizeof(char) * 6;
wrapper = malloc(sizeof(char) * 8);
I = strcpy(I, "I\0");
am = strcpy(am, "am\0");
a = strcpy(a,"a\0");
great = strcpy(great, "great\0");
wrapper = strcpy(wrapper, "wrapper\0");
void * ret;
printf("Sum = %f\n", *( (double*)super_wrapper(sum, ret, 3, &two, &three, &fifteen) ) );
super_wrapper(my_print, ret, 5, &I, &am, &a, &great, &wrapper);
}