如何将“带有参数的函数的指针”传递给另一个函数

时间:2019-05-29 07:53:06

标签: c

我具有以下系统功能:

int sock_yield( void *s, void (*fn)() );

我需要传递一个带有2个参数的函数:

void reset(char buf,udp_Socket sock) {

    if (-1 == udp_recv(&sock, &buf, sizeof(buf)));

    if(buf=='R')
    {

        printf("\nReceived-> %c",buf);

        forceSoftReset();

        forceWatchdogTimeout();

    }

}

在调用sock_yield函数时,只能给它传递函数名称而不带参数: sock_yield(sock, reset)

如何指定要传递给reset的{​​{1}}的参数?

2 个答案:

答案 0 :(得分:5)

您不能这样做。严格说来,在不同函数类型之间进行转换是未定义的行为,尽管某些编译器具有非标准扩展名,在某种程度上允许它。

此外,void (*fn)()表示带有任何参数的函数,该函数已过时,样式为C,不应使用。

因此必须重写sock_yield函数。如果要使用回调函数作为参数,那么它从一开始就很糟糕。它应采用一种特定的指定格式的函数指针。例如:

typedef void sock_callback_t (char buf, udp_socket* sock);

int sock_yield(void* s, sock_callback_t* fn); 

或者,您可以编写一些技巧,在函数指针和uintptr_t之间进行转换,但这是一个较差的解决方案,仅当您使用书写不良的API时才应使用。

答案 1 :(得分:1)

您不能。 C只知道函数的原始指针。然后,您可以在使用指针时提供所有必需的参数。示例:

int double(int i) {
    return 2*1;
}

int exec_op(int param, int (*op)()) {
   return op(param);
}

之所以可行,是因为在C中,无效参数列表意味着该函数可以接受任何参数。

如果在用例sock_yield中调用不带参数的函数,则唯一的选择是使用带有全局参数的包装器:

char Buf;
udp_Socket Sock;

void reset_wrapper(void) {
    reset(Buf, Sock);
}

,然后以这种方式使用它:

    Buf = buf;
    Sock = sock;
    sock_yield(s, &reset_wrapper);