【问题标题】:How to pass function pointers with call stack?如何通过调用堆栈传递函数指针?
【发布时间】:2013-04-24 17:25:28
【问题描述】:

我不确定我是否有这个问题的最佳标题,请随时改进。

如果我有

typedef void (*VoidFunction)(void);

然后是适合这种类型的一系列函数,我可以编写一种“事务”包装函数,如下所示:

void doTransaction(VoidFunction function)
{
    doSomePreambleWork();
    function();
    doSomePostambleWork();
}

如果我有一系列接受单个 int 参数的函数,我可以清洗-冲洗-重复:

typedef void (*VoidOneIntFunction)(int a);
void doTransactionOneInt(VoidFunctionOneInt function, int a)
{
    doSomePreambleWork();
    function(a);
    doSomePostambleWork();
}

离开返回类型的问题(iow,假设返回类型为 void),是否可以泛化这种模式,这样我只需要编写一个包装函数,例如:

// ????? I'm not sure how i'd type the passed function
void doTransactionGeneric(void * function, ...)
{
    doSomePreambleWork();
    function(); // ????? and i don't know how i'd go about calling it...
    doSomePostambleWork();
}

【问题讨论】:

  • 看看<stdarg.h> 标头。解决方案是使用可变参数列表。
  • @Will 我认为这不是 OP 所要求的。
  • 我希望得到比这些答案更“元”的东西。也许用 C 是不可能的。我想我可以以某种方式弄乱堆栈,以某种方式神奇地调用调用堆栈的第一个参数(已知是一个函数)和调用堆栈的其余部分。 :(

标签: c


【解决方案1】:

如果您想使用... 语法,即可变参数,则使用va_list 访问参数列表,例如:

#include <stdarg.h>

typedef void (*VoidArgsFunction)(va_list args);

void doTransactionGeneric(VoidArgsFunction function, ...)
{
    doSomePreambleWork();

    va_list args;
    va_start(args, function);
    function(args);
    va_end(args);

    doSomePostambleWork();
}

在被调用函数内部,可以根据需要使用va_arg()来访问va_list中的各个参数值​​,例如:

#include <stdarg.h>

void someFunction(va_list args)
{
    int param1 = va_arg(args, int);
    char *param2 = va_arg(args, char*);
    ...
}

doTransactionGeneric(&somefunction, 12345, "Hello World");

【讨论】:

    【解决方案2】:

    我不确定如何输入传递的函数

    就像在其他任何地方声明函数指针一样:

    void doTransactionGeneric(void (*function)(void), ...)
    

    我不知道该怎么称呼它......

    就像你已经做过的那样:

    function();
    

    【讨论】:

    • 如果你这样声明function,你将无法将可变参数传递给doTransactionGeneric()本身并将它们传递给指定的函数。
    【解决方案3】:

    这是一个建议。

    假设你有几个功能(就像你的问题一样):

    typedef void (*VoidFunction)(void);
    typedef void (*VoidFunctionOneInt)(int);
    // we can add more
    

    让我们定义类型枚举(我们不必使用枚举,但这更能说明问题):

    typedef enum
    {
       e_fn_void,     // void return, no args
       e_fn_void_int, // void return, one int
                      // we can add more...
    } void_function_kind_t;
    

    然后,假设我们有一些通用处理器。我们需要提供函数的类型、函数指针和参数:

    void some_generic_function(void_function_kind_t kind, void *fn, ...)
    {
       va_list args;
       va_start(args, fn);
    
       // here - make a call
       switch (kind)
       {
       case e_fn_void:
            // no arguments
            ((VoidFunction)fn)();
            break;
       case e_fn_void_int:
            {
               int arg0 = va_arg(args,int);
               ((VoidFunctionOneInt)fn)(arg0);
            }
            break;
       default: // error - unsupported function type
            break;
       }
    
       va_end(args);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-19
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      • 2013-04-14
      • 2017-03-26
      相关资源
      最近更新 更多