Использование лямбда-функции для функции обратного вызова в качестве параметра функции C - PullRequest
3 голосов
/ 03 мая 2020

Я писал свою собственную std::thread -подобную оболочку для pthread_* функций (в образовательных целях). Конструктор, который я придумал, выглядел так:

template<class Fn, class... Args>
explicit Thread(Fn&& fn, Args&&... args) {
    using Invoker = Thread_invoker<Fn, Args...>;
    void* (* start_fn)(void*) = [](void* invoker_ptr) -> void* {
        // ...
    };

    auto invoker = std::make_unique<Invoker>(/* ... */);
    const auto err = ::pthread_create(&handle_, nullptr, start_fn, invoker.get());
    // ...
    invoker.release();
}

Я сделал несколько базовых c тестов, код работает. Но потом мне пришло в голову, что функции C ++ теоретически могут иметь соглашения о вызовах, отличные от C функций, и передача указателя функции start_fn на pthread_create может быть UB. Этот ответ , кажется, подтверждает это.

Копая дальше, я нашел этот вопрос . Следуя духу принятого ответа , я изменил свой код следующим образом:

extern "C" using Thread_start_fn = void* (void*);

Thread_start_fn* start_fn = [](void* invoker_ptr) -> void* {
    // ...
};

Решает ли это изменение проблему и является ли код законным в настоящее время?

1 Ответ

4 голосов
/ 03 мая 2020

Эта модификация решает проблему и является ли код законным сейчас?

Нет, это не решает проблему. Указатель на функцию, который вы можете получить из лямбда-выражения, относится только к функции с языковой связью C ++ .

. Способ с уверенностью получить указатель на функцию с языковой связью C использовать бесплатную функцию. Такой подход вы увидите в популярных реализациях стандартных библиотек. Например, в libstdc ++

extern "C"
  {
    static void*
    execute_native_thread_routine(void* __p)
    {
      thread::_State_ptr __t{ static_cast<thread::_State*>(__p) };
      __t->_M_run();
      return nullptr;
    }
    // ...
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...