Как передать «указатель на функцию с параметрами» в другую функцию - PullRequest
2 голосов
/ 29 мая 2019

У меня есть следующая системная функция:

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 для передачи sock_yield?

Ответы [ 2 ]

5 голосов
/ 29 мая 2019

Вы не можете сделать это. Преобразование между различными типами функций строго говоря, неопределенное поведение, хотя некоторые компиляторы имеют нестандартные расширения, которые позволяют это в некоторой степени.

Кроме того, 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 голос
/ 29 мая 2019

Вы не можете. 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...