Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C:将任何函数传递给函数_C_Function_Pointers_Function Pointers_Generic Programming - Fatal编程技术网

C:将任何函数传递给函数

C:将任何函数传递给函数,c,function,pointers,function-pointers,generic-programming,C,Function,Pointers,Function Pointers,Generic Programming,我想知道如何将任何函数传递给函数,就像在一个可以接受任何函数的通用函数指针中一样,这样做的目的是生成一个析构函数系统,因此基本上存储函数并使用它的参数调用它,这些参数以后也会存储 比如: Defer(SDL_DestroyWindow, Window); 我已经处理了参数,但是我不知道如何管理函数指针部分,谢谢 编辑:我添加了更多信息 typedef struct { void** args; } IM_Defer_Resource; /* Defer & Whatnot */

我想知道如何将任何函数传递给函数,就像在一个可以接受任何函数的通用函数指针中一样,这样做的目的是生成一个析构函数系统,因此基本上存储函数并使用它的参数调用它,这些参数以后也会存储

比如:

Defer(SDL_DestroyWindow, Window); 

我已经处理了参数,但是我不知道如何管理函数指针部分,谢谢

编辑:我添加了更多信息

typedef struct {
  void** args;
} IM_Defer_Resource;
/* Defer & Whatnot */

IM_Stack* IM_Defer_Stack;

void IM_Defer_Init() {
  IM_Defer_Stack = IM_Stack_Init();
}


void IM_Defer(/* What to put here? */) {

}

void IM_Defer_All() {
  while(IM_Defer_Stack->size) {
    IM_Defer_Resource* resource = IM_Stack_Pop(IM_Defer_Stack);
    if(!resource) continue;
    /* What to do */
  }
}
我没有defer的实际函数,但我确实将每个参数复制到堆栈中并成功地弹出它们,但我不知道如何实现可变函数调用

编辑2: 在收到一些意见后:我认为这更可行: 延迟(SDL_窗口,“SDL_窗口*”,窗口); 我正在集思广益,讨论如何实现这一点,但我希望能提供一些意见

编辑3:

/* Defer & Whatnot */
typedef struct {
  char** types;
  void** args;
  int count;
} IM_Defer_Resource;


IM_Stack* IM_Defer_Stack;

void IM_Defer_Init() {
  IM_Defer_Stack = IM_Stack_Init(IM_Get_Stack_Type(IM_Defer_Resource));
}

void IM_Defer_Internal(void* var, int n, ...) {
  char* type;
  void* arg;

  va_list args;
  va_start(args, n);

  IM_Defer_Resource resource;
  int count = n / 2;
  resource->types = calloc(count, sizeof(char*));
  resource->args = calloc(count, sizeof(void*));
  resource->count = count;

  for(count > 0; n -= 1) {
    type = va_arg(args, char*);
    resource->types[count-1] = type;
    arg = va_arg(args, void*);
    resource->args[count-1] = arg;
  }

  IM_Stack_Push(IM_Defer_Stack, &resource);
}

void IM_Defer_All() {
  while(IM_Defer_Stack->size) {
    IM_Defer_Resource* resource = IM_Stack_Pop(IM_Defer_Stack);
    if(!resource) continue;
    /* I have a char* and a void* to the resource, Now what? */
    free(resource->types);
    free(resource->args);
  }
}

这就是我想到的,但我想知道如何将char*转换为类型…

正如我在评论中所说的,一个大问题是,当声明一个变量函数时,未声明的参数受
默认参数的影响。这意味着您可以找到传递的参数与函数预期的参数不同,这将最终导致异常。你想做的是可行的,但实际上非常复杂

一种解决方案可能是:

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

typedef enum { fn1, fn2, fn3, /*....*/} e_fn;

void multi_fun(e_fn fn, ...)
{
    va_list ap;
    int j;

    va_start(ap, fn); /* Requires the last fixed parameter (to get the address) */

    switch(fn)
    {
        case fn1:
        {
            //suppose prototype for fn1 to be void fn1_fn(int, float, struct  mystruct *);
            int   this_int   = va_arg(ap, int);
            float this_float = va_arg(ap, float);
            struct  mystruct *this_struct = va_arg(ap, struct  mystruct *);
            fn1_fn(this_int, this_float, this_struct);
            break;
        }

        case fn2:
        {
            ...
        }
    }
    va_end(ap);
}
#包括
#包括
typedef枚举{fn1,fn2,fn3,/*../}e_fn;
无效的多重乐趣(e_fn fn,…)
{
va_列表ap;
int j;
va_start(ap,fn);/*需要最后一个固定参数(获取地址)*/
开关(fn)
{
案例fn1:
{
//假设fn1的原型为void fn1u fn(int,float,struct mystruct*);
int this_int=va_arg(ap,int);
浮动此浮动=va浮动参数(ap,浮动);
struct mystruct*此_struct=va_arg(ap,struct mystruct*);
fn1_fn(这个int,这个float,这个struct);
打破
}
案例fn2:
{
...
}
}
va_端(ap);
}

您应该看看GitHub。他们使用宏来缓存模拟函数。麻省理工学院授权。然而,正如@Frankie_C所说,这需要大量代码。定义所有宏的头文件大约为6K LOC。函数仍然被限制为20个参数。

您可能可以使用可变宏技巧来做一些事情,尽管我对此已经不太熟悉;)一种类型的任何函数指针都可以转换为另一种类型的函数指针。因此,使用
foo(int(*f)(){…}
就足以传递函数指针(值)。诀窍是如何通过类型。代码对有限的类型列表使用一个联合和一个枚举值-但任何类型?-->建议缩小目标范围。@chux-然后问题是如何将可变数量的参数传递给(非可变)函数指针。“我已经处理了参数”-->发布这样做的代码将增加目标的清晰度。正如我所说,可能会有,但非常复杂。如果您有一个支持C11的编译器,您也可以尝试使用
\u Generic
进行泛型选择,制作一组包含一组参数的包装函数,这些参数可以适合您想要使用的任何类型的函数,然后仅使用适当的参数在本地调用该函数。认为这是人们选择C++的原因之一…