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

标签 c++ c lambda extern-c

我正在为 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 answer似乎证实了这一点。

进一步挖掘,我发现 this question .遵循接受的精神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;
    }
    // ...
  }

关于c++ - 将 lambda 用于回调函数作为 C 函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61572399/

相关文章:

c++ - 如何在没有 if 语句的情况下返回可选的<T>?

c++ - LIBC 的 mktime 函数对相同的输入返回不同的值

c - 用不同的指针重新分配重叠指针

c++ - Lambda 隐式捕获因结构化绑定(bind)声明的变量而失败

c++ - 创建与推导参数具有相同类型的局部变量的最简单方法是什么?

c++ - 使用 lambda 进行变体访问的最佳方法

c++ - 我可以隐式创建一个可简单复制的类型吗

javascript - 使用 v8 读取二进制文件的函数

c++ - 将 lambda 传递给 std::thread 并调用类方法

c - 自己的简单VPN的数据包封装