Передача лямбда-выражений в виде обратных вызовов в функции C - PullRequest
2 голосов
/ 28 марта 2019

Предположим, у меня есть функция C

typedef void (* callback_t)(void* data);
status_you_dont_care_about register_callback(callback_t callback, void* data);

и я хочу передать лямбду в качестве обратного вызова.

Какой идиоматический способ сделать это ...

  1. Когда лямбда ничего не захватывает?
  2. Когда лямбда имеет захваты (по значению, по ссылке и т. Д.)?

1 Ответ

0 голосов
/ 28 марта 2019

Случай без захвата

Как указывают комментаторы, лямбда неявно преобразуется в указатель на функцию соответствующего типа, поэтому мы можем просто написать:

auto my_lambda = [](void* data) { /* do stuff here */};
register_callback(my_lambda, get_pointer_to_data());

и это скомпилируется. Не забудьте проверить возвращаемое значение: -)

Футляр для захвата

Вот что я сейчас делаю, но я подозреваю, что это неоптимально.

Сначала я проверяю, что лямбда захватывает все, что ему нужно, чтобы он сам вызывался с параметрами без (так что на самом деле не принимает void* как обратный звонок должен). Тогда я использую этот код:

template <typename Invokable>
void callback_adapter(void *invokable_on_heap)
{
    auto retyped_callback = std::unique_ptr<Invokable>{
        reinterpret_cast<Invokable*>(invokable_on_heap)
     };
    (*retyped_callback)(std::forward<Ts>(parameters)...);
    // Note: invokable_on_heap will be delete'd
}

template <typename Invokable>
void register_invokable_as_callback(Invokable callback_) {
    Invokable* invokable_on_the_heap = new Invokable(std::move(callback_));
    register_callback(&callback_adapter<Invokable>, invokable_on_the_heap);
}

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

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