【问题标题】:Wrap several functions with difference argument counts in on wrapper function在包装函数中包装几个具有不同参数计数的函数
【发布时间】:2019-01-28 22:16:31
【问题描述】:

我有几个功能:

int do_one_thing(struct my_struct *s, struct other_struct *os);
int do_another_thing(struct third_struct *ts, struct fourth_struct *s, int i);
int do_even_more_stuff(float *f, struct fourth_struct *s, int i);

我想用一个像这样的函数来包装所有这些

/* 
this is basically: 
int wrapper_function(<function name>, <wrapped_function>, <arguments for wrapped function>)
*/
int wrapper_function(const char *fname, function *fun, ... )
{
    int fun_ret = 0;
    fun_ret = fun(b, args);

    printf("Function %s returned %d\n", fname, fun_ret);
    return fun_ret;
}

显然,所有对 do_one_thing、do_another_thing 或 do_even_more_stuff 的函数调用都将替换为对 wrapper_function 的调用。

那么,我该怎么做呢?

挑战在于传递变量参数和函数签名。

我不想使用宏。

【问题讨论】:

  • 我不认为 _Generic 可以使用可变数字参数
  • 您通常不能根据C 中的参数调用具有相同名称的不同函数。具体来说,具有可变数量参数的函数需要一种方法来判断参数数量以及它们是什么。
  • 查看stdarg,它具有处理变量参数列表的宏:va_startva_argva_end。但是请注意,当使用可变参数列表时,您将失去编译器提供的所有参数存在和类型检查。官方称这些为variadic functions

标签: c


【解决方案1】:

http://c-faq.com/varargs/varargs1.html

#include <stdarg.h>
#include <stdio.h>  /* printf */

struct my_struct {
    int i;
};

struct other_struct {
    char a;
};

struct third_struct {
    float f;
};

struct fourth_struct {
    double d;
};

static int do_one_thing(struct my_struct *s, struct other_struct *os) {
    printf("do one thing %d %c.\n", s->i, os->a);
    return s->i;
}

static int do_another_thing(struct third_struct *ts, struct fourth_struct *s,
    int i) {
    printf("do another thing %f %f %d.\n", ts->f, s->d, i);
    return i;
}

static int do_even_more_stuff(float *f, struct fourth_struct *s, int i) {
    printf("do even more stuff %f %f %d.\n", *f, s->d, i);
    return i;
}

enum Fn { ONE, ANOTHER, STUFF };

static int wrapper_function(const enum Fn fn, ... ) {
    va_list argp;
    int fun_ret = 0;
    struct my_struct *s;
    struct other_struct *os;
    struct third_struct *ts;
    struct fourth_struct *fs;
    int i;
    float *f;

    va_start(argp, fn);

    switch(fn) {
        case ONE:
            s = va_arg(argp, struct my_struct *);
            os = va_arg(argp, struct other_struct *);
            fun_ret = do_one_thing(s, os);
            break;
        case ANOTHER:
            ts = va_arg(argp, struct third_struct *);
            fs = va_arg(argp, struct fourth_struct *);
            i = va_arg(argp, int);
            fun_ret = do_another_thing(ts, fs, i);
            break;
        case STUFF:
            f = va_arg(argp, float *);
            fs = va_arg(argp, struct fourth_struct *);
            i = va_arg(argp, int);
            fun_ret = do_even_more_stuff(f, fs, i);
            break;
    }

    va_end(argp);

    return fun_ret;
}

int main(void) {
    struct my_struct s = { 42 };
    struct other_struct os = { 'z' };
    struct third_struct ts = { 3.14f };
    struct fourth_struct fs = { 0.9999 };
    float f = 2.001;
    int r0, r1, r2;
    printf("Function one returned %d.\n"
        "Function another returned %d.\n"
        "Function stuff returned %d.\n",
        r0 = wrapper_function(ONE, &s, &os),
        r1 = wrapper_function(ANOTHER, &ts, &fs, 99),
        r2 = wrapper_function(STUFF, &f, &fs, -3));
    return 0;
}

但是,我真的看不出有什么优势;一个是增加开销并且基本上关闭类型检查。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    相关资源
    最近更新 更多