首页 > 解决方案 > 在 C++ 中无状态地包装 C 回调接口

问题描述

我需要在 C++ 中无状态地包装 C 接口的回调机制,以接受可调用对象,即包装类不应有任何非 const 成员。在 C 接口中(不在我的控制之下)有一个添加回调的函数:

void c_add_callback(void(*callback)(void* context), void* context)

这是我尝试将 C 接口包装在一个接受对可调用对象的引用的类中:

class CppWrapper
{
public:
    // C++ callable parameter
    template<typename Function>
    void AddCallback(Function& function)
    {
        c_callbacks_.push_back
            ([](void* context)
                {
                    (*reinterpret_cast<Function*>(context))();
                }
            );
        c_add_callback
            (c_callbacks_.back()
            , reinterpret_cast<void*>(&function)
            );
    }
private:
    // storage of c callbacks
    std::list<void(*)(void*)> c_callbacks_;
};

显然,这种方法不是无状态的,因为我必须将回调(成员 c_callbacks_)存储为传递给 C 接口,否则传递给 c_add_callbacks 的 lambdas 将是临时的,并且会在 c_add_callback 返回时被破坏,请参阅Casting a universal reference to可调用 void 指针,反之亦然

有没有办法实现包装类无状态,即摆脱成员?

有关完整代码示例,请参阅https://onlinegdb.com/rkeh-UNX0U

一些背景: 使包装器无状态的意图来自于 C 接口背后的库可能在某些时候处理所有添加的回调的事实。显然,当循环添加回调并触发库处理它们时,这将导致列表不断增长(成员 c_callbacks_)。如果 dispose 操作没有通过 C 接口传播,我该如何处理这种泄漏?

标签: cc++11

解决方案


我根本不理解你想要达到什么目的c_callbacks_c_callbacks_.back()您只在, 之后直接使用它c_callbacks_.push_back()

只需使用

c_add_callback([](void* context)
    {
       (*reinterpret_cast<Function*>(context))();
    },
    reinterpret_cast<void*>(&function));

注意:与您的示例一样,这假设 的生命周期&function是外部管理的。


推荐阅读