将 lambda 用于回调函数作为 C 函数参数

Using lambda for callback function as C function parameter

我正在为 pthread_* 函数编写自己的 std::thread 类包装器(出于教育目的)。我提出的构造函数如下所示:

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函数的调用约定,将start_fn函数指针传递给pthread_create可以是UB。 似乎证实了这一点。

进一步挖掘,我发现 this question. Following the spirit of the accepted answer,我将代码更改为:

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

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

这个修改是否解决了问题,现在代码合法了吗?

Does this modification solve the problem and is the code legal now?

不,它不能解决问题。您可以从 lambda 表达式中获得的函数指针仅指向 function with C++ language linkage.

确定地获得指向具有C语言链接的函数的指针的方法是使用自由函数。这是您将在流行的标准库实现中看到的方法。例如,in 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;
    }
    // ...
  }