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

C-将带参数的函数传递到包装器执行器,c,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中传递arumges,或者只

有没有一种方法可以在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
中传递arumges,或者只支持
func
的一种方法头。我已经写了很多Javascript。。。当然,这在JS中是可能的。

您考虑过(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"));
}
#包括
#定义包装器(f)/*设置*/\
f\
/*清理*/
无效foo(整数x,整数y){
printf(“x:%d;y:%d\n”,x,y);
}
空栏(字符*str){
printf(“str:%s\n”,str);
}
内部主(空){
包装物(foo(42,11));
包装(酒吧(“你好世界”);
}
为了详细说明为什么我在(ab)用法中添加了ab前缀,我会毫不犹豫地使用任何最能表达问题的解决方案,而不考虑胡杨的态度。然而,我认识到,有时我们无法控制我们所受的限制,而且往往制定政策来严格限制宏的使用。不幸的是,那些受这些愚蠢政策束缚的人不会觉得这篇文章太有帮助

在上面的一条评论中,我建议“如果你想从Javascript中获得一个特性,你可能应该用Javascript编写你的代码……”

经过一夜之间的思考,我得出结论,与您要求的功能类似的功能实际上是可行的,在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");
}
#包括
结构参数;
typedef结构参数;
typedef void函数(参数*);
结构参数{
功能*功能;
/*for foo()*/
int x;
int-y;
/*对于bar()*/
char*str;
};
无效包装器(参数*a){
//设立
a->功能(a);
//清理
}
void foo(参数*a){
printf(“x:%d;y:%d\n”,a->x,a->y);
}
无效条(参数*a){
printf(“str:%s\n”,a->str);
}
#定义foo(…)包装器(&(参数){.function=foo,_VA_ARGS__})
#定义条(…)包装(&(参数){.function=bar,.str=“”,uu VA_ARGS_uu})
内部主(空){
foo(.x=42,.y=11);
酒吧(.str=“hello world”);
}
实际上,这种包装方式有一些非常好的特性:

  • 下游编程人员很难使用堆栈,因为程序员很容易使用典型的可变函数,例如
    printf
    scanf
    ,通过向这些函数传递错误的类型和/或值,导致微妙但破坏性的错误。这引出我的下一点:
  • 只需修改
    foo
    bar
    宏,就可以使用默认参数值。作为上面代码中的一个示例,名为
    str
    的参数的默认值被设置为
    (一个空字符串),用于
    bar
  • 通过在
    包装器中引入额外的逻辑,您可以模拟部分函数应用程序(或者将属性绑定到函数,就像在Javascript中看到的那样)。此外,只需稍加努力,就可以通过将
    包装器
    转换为蹦床式函数并修改返回值来模仿连续传递方式?我将对此进行更多思考,并在明天提供更新
  • 最后,鼓励下游用户将参数标识符与参数值配对,这大大提高了可维护性
有一些小的回退,最重要的是
foo
bar
都不能作为参数传递给另一个函数。这对于这些函数来说是非常罕见的,因为它们在签名上有很大的不同,但是对于签名相同甚至相似的函数,我可以理解人们可能希望将它们作为回调传递,或者什么都不传递

解决这个问题的方法是将宏重命名为
default\u foo
default\u bar
或类似的东西


最后,谢谢你提出这样一个发人深省的问题。。。我希望阅读我的答案对你来说就像思考(和写作)它对我一样有趣。

这是我能想到的变量函数的最佳选择:

#include <stdio.h>
#include <stdarg.h>

void wrapper(void (*func)(va_list), ...) {
    va_list args;
    va_start(args, func);

    func(args);

    va_end(args);
}

void foo(int x, int y)
{
    printf("foo(%d,%d)\n", x, y);
}
void vfoo(va_list args)
{
    foo(va_arg(args, int), va_arg(args, int));
}
void bar(char *z)
{
    printf("bar(%s)\n", z);
}
void vbar(va_list args)
{
    bar(va_arg(args, char*));
}

int main()
{
    wrapper(vfoo, 1, 2);
    wrapper(vbar, "Hello, World!");
    return 0;
}
#包括
#包括
无效包装(无效(*func)(va_列表),…){
va_列表参数;
va_启动(参数、函数);
func(args);
va_端(args);
}
无效foo(整数x,整数y)
{
printf(“foo(%d,%d)\n”,x,y);
}
void vfoo(va_列表参数)
{
foo(va_arg(args,int),va_arg(args,int));
}
空栏(字符*z)
{
printf(“条(%s)\n”,z);
}
无效vbar(VAU列表参数)
{
bar(va_arg(args,char*);
}
int main()
{
包装器(vfoo,1,2);
包装器(vbar,“你好,世界!”);
返回0;
}

.

你可以使用一个变量函数作为包装器。@ForceBru所以我需要在
包装器
中使用某种分支逻辑来区分
foo
bar
?另一方面,如果你想从Javascript中获得一个特性,你可能应该用Javascript编写你的代码……不确定我是否同意你的观点。我想从Javascript/Python/等中获得很多功能,但鉴于我正在编写一个基本的操作系统,我认为这是不可能的。酷-我想你不需要包装器中的任何逻辑。
\define
需要parentheses@ringø你指的是哪个
#定义
?那么第一个呢?我认为你错了。OP明确地希望能够调用
包装器
中具有不同签名的函数,例如:
包装器(foo(42,11));包装(酒吧(“你好世界”)…我确实弄错了;-)@先生周四在考虑了您的需求一段时间后,我得出结论,当我建议使用Javascript(在评论中)时,我错了。请看我的编辑;希望你能找到s