c++ - 将 lambda 用于回调函数作为 C 函数参数
问题描述
我正在为函数编写自己的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函数的调用约定,传递start_fn
函数指针pthread_create
可以是UB。这个答案似乎证实了这一点。
进一步挖掘,我发现了这个问题。按照公认答案的精神,我将代码更改为:
extern "C" using Thread_start_fn = void* (void*);
Thread_start_fn* start_fn = [](void* invoker_ptr) -> void* {
// ...
};
这个修改是否解决了问题,代码现在合法吗?
解决方案
这个修改是否解决了问题,代码现在合法吗?
不,它不能解决问题。您可以从 lambda 表达式获得的函数指针仅指向具有 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;
}
// ...
}
推荐阅读
- regex - 替换匹配的 START END 行
- python - 我试图将我的文件夹推送到 Heroku 并得到以下消息
- javascript - JavaScript ES 承诺履行处理程序作业队列是否在所有 setTimeout 和 setInterval 处理程序队列之前执行?
- c# - 无法点击网址
- flutter - 从资产文件夹创建文件
- java - 钻取错误:UNSUPPORTED_OPERATION 错误:VarChar 类型仅支持 COUNT、MIN 和 MAX 聚合函数
- python - Django简单历史继承从父到子历史
- python - 如何使用 ModelChoiceField 显示模型的“名称”字段
- angular - Angular rxjs Observer 通用类型需要 1 个参数
- firebase - 将 image_picker 添加到在颤振中使用 firebase_auth 的应用程序时构建失败