Как назначить тип sdt :: function для sigevent.sigev_notify_function (таймеры POSIX) - PullRequest
0 голосов
/ 16 января 2019

Я использую таймер POSIX для вызова функции, определенной с помощью шаблона std :: function:

typedef std::function<void (union sigval)> functionCbType;

Я получаю следующую ошибку при присвоении полю sigev_notify_function struct sigevent:

ошибка: невозможно преобразовать ‘functionCbType {aka std :: function}’ в ‘void () (sigval_t) {aka void () (sigval)}’ в назначении se.sigev_notify_function = callcbk;

functionCbType callcbk;
...
struct sigevent se;
se.sigev_notify = SIGEV_THREAD;
se.sigev_notify_function = callcbk;
se.sigev_notify_attributes = NULL;

int status = timer_create(CLOCK_MONOTONIC, &se, &timer_id);

se.sigev_notify_function ожидает

void       (*sigev_notify_function) (union sigval);

Как правильно это сделать?

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Хорошо разработанный API обратного вызова C позволяет передавать значение в функцию обратного вызова. Это позволяет вам иметь обратные вызовы с отслеживанием состояния.

В этом случае union sigval является объединением int и void*. Вы должны придерживаться своего состояния в любом из этих двух.

std::function<Sig> может хранить состояние, поэтому вам нужно передать это состояние через.

A std::function не является указателем на функцию. Чтобы передать его API-интерфейсу обратного вызова функции C, вам нужно обернуть его и передать как часть void*.

struct sig_cb {
  void(* function)(sigval_t);
  void* pvoid;
};
sig_cb make_signal_callback( std::function<void()>* pf ) {
  return {
    [](sigval_t v) { (*static_cast<std::function<void()>*>(v.sival_ptr))(); },
    pf
  };
}

затем измените ваш код:

functionCbType callcbk;
...
struct sigevent se;
auto cb = make_signal_callback(&callcbk);
se.sigev_notify = SIGEV_THREAD;
se.sigev_notify_function = cb.function;
se.sigev_value.sival_ptr = cb.pvoid;
se.sigev_notify_attributes = NULL;

int status = timer_create(CLOCK_MONOTONIC, &se, &timer_id);

и оно должно работать. Естественно, время жизни вашего std::function должно управляться отдельно.

0 голосов
/ 16 января 2019

Структуры sigevent sigev_notify_function не ожидают объект std::function, он ожидает указатель функции:

void       (*sigev_notify_function) (union sigval);

Объект std::function может быть создан неявно из указателя функции, но обратное невозможно. Вы должны использовать указатель на фактическую функцию.

Этого можно добиться, используя callcbk.target<void(*)(union sigval)>(), чтобы получить указатель на исходный указатель функции, но тогда callcbk несколько бессмысленно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...