C - 将带参数的函数传递给包装器执行器

时间:2015-11-24 13:56:24

标签: c

有没有办法在C中构建包装函数,如下所示:

void wrapper(void *func) {
  // Set up
  func([same arguments as func was passed in with]);
  // Clean up
}

void foo(int x, int y);
void bar(char *z);

wrapper(foo(1, 2));
wrapper(bar("Hello"));

好像你必须传递wrapper中的句子,或者只支持func的一种方法标题。我一直在写很多Javascript ......当然这在JS中是可能的。

2 个答案:

答案 0 :(得分:4)

使用可变函数wwrappers,我能想到的最好:

default_foo

Live example on Coliru

答案 1 :(得分:3)

您是否考虑过(ab)使用预处理器?

#include <stdio.h>

#define wrapper(f) /* Set up   */\
                   f;            \
                   /* Clean up */

void foo(int x, int y) {
    printf("x: %d; y: %d\n", x, y);
}

void bar(char *str) {
    printf("str: %s\n", str);
}

int main(void) {
    wrapper(foo(42, 11));
    wrapper(bar("hello world"));
}

为了详细说明为什么我增加了ab-前缀用于(ab)使用的可能性,我不会犹豫是否使用任何最具表现力的解决方案来解决问题,无论普通杨树的态度如何。但是,我认识到,有时我们无法控制受限制的限制,并且通常会制定策略来严格限制宏的使用。不幸的是,受这些愚蠢政策约束的人不会发现这篇文章太有用了。

在上面的评论中,我建议&#34;如果你想要一个Javascript的功能,你应该用Javascript编写你的代码......&#34;。

在一夜之间思考这个问题后,我得出的结论是,与你提出的相似的功能实际上是可行的并且在C中会很好......所以我承认,我错了。

以下是模仿Javascript处理函数的示例。

#include <stdio.h>

struct argument;
typedef struct argument argument;
typedef void function(argument *);

struct argument {
    function *function;

    /* for foo() */
    int x;
    int y;

    /* for bar() */
    char *str;
};

void wrapper(argument *a) {
    // set up
    a->function(a);
    // clean up
}

void foo(argument *a) {
    printf("x: %d; y: %d\n", a->x, a->y);
}

void bar(argument *a) {
    printf("str: %s\n", a->str);
}

#define foo(...) wrapper(&(argument){ .function = foo, __VA_ARGS__ })
#define bar(...) wrapper(&(argument){ .function = bar, .str = "", __VA_ARGS__ })

int main(void) {
    foo(.x = 42, .y = 11);
    bar(.str = "hello world");
}

实际上有一些非常好的功能来自这种包装器:

  • 下游程序员很难 mung堆栈 ,因为对于使用典型的可变参数函数的程序员来说非常容易,例如{{1通过将错误的类型和/或值传递给这些函数,导致细微但毁灭性的错误。}和printf这导致我的下一点:
  • 只需修改scanffoo宏,即可
  • 默认参数值。作为上面代码中的示例,名为bar的参数的默认值设置为str的{​​{1}}(空字符串)。
  • 通过在""中引入额外的逻辑,您可以模仿部分函数应用程序(或函数的绑定属性,就像您在Javascript中看到的那样)。另外,通过一点努力,通过将bar转换为蹦床式函数并修改返回值,可以模仿继续传递样式 ?我会对此进行更多思考并明天提供更新。
  • 最后,鼓励下游用户将参数标识符与参数值配对,这极大地提高了可维护性。

有一些小的缺点,最重要的是,wrapperwrapper都不能作为参数传递给另一个函数。这对于这些函数来说很少见,因为它们在签名方面差异很大,但对于签名中相同或甚至相似的函数,我可以理解,人们可能希望将它们作为回调或什么不传递。

该问题的解决方案是将宏重命名为foobar或类似的内容......

最后,感谢您提出这样一个发人深省的问题......我希望阅读我的答案对您来说同样有趣,因为它(和写作)对我来说很有意义。