c++ - 将 lambdas 作为回调传递给 C 函数
问题描述
假设我有一个 C 函数
typedef void (* callback_t)(void* data);
status_you_dont_care_about register_callback(callback_t callback, void* data);
我想传递一个 lambda 作为回调。
这样做的惯用方法是什么...
- 当 lambda 什么都没有捕获?
- 当 lambda 有捕获(按值、按引用等)?
解决方案
非捕获案例
正如评论者指出的那样,lambda 隐式转换为适当类型的函数指针,所以我们可以写:
auto my_lambda = [](void* data) { /* do stuff here */};
register_callback(my_lambda, get_pointer_to_data());
这将编译。不过不要忘记检查返回值:-)
抓包案例
这就是我目前正在做的事情,但我怀疑它不是最理想的。
首先,我确保 lambda 捕获它需要的所有内容,以便它本身可以在没有参数的情况下调用(因此它实际上不需要像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);
}
注意:使用这种方法,回调只能被调用一次。它可以适应需要多次调用的回调的情况,在取消注册/销毁任何调用回调时解除分配。
推荐阅读
- javascript - 类型错误:this.$el.bracket 不是函数
- c++ - 在 OpenCV 中定义初始化的 3D 矩阵 Mat_ 的一个衬垫
- javascript - 如何以编程方式知道 Mongo Realm 中的错误登录?
- git - gitignore 不适用于我的后端文件夹中的 process.env
- reactjs - 反应 | Redux-Form | 字段 为字段分配状态
- aws-cli - 将 AWS 的全屏“菜单”输出更改为标准输出?
- python - 数组和列表项目
- reactjs - 将静态 Next.js 应用部署到 Firebase 托管
- c - 执行 strncpy 以指向字符串数组的指针时出现分段错误 C
- r - 在 facet_grid() 上使用 lapply 函数生成的多个 ggplot 的网格布局