vendredi 26 juin 2020

Statelessly wrap a C callback interface in C++

I need to wrap a callback mechanism of a C interface statelessly in C++ accepting callables, i. e. the wrapper class shall not have any non-const members. In the C interface (not under my control) there is a function to add a callback:

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

Here is my attempt to wrap the C interface in a class accepting a reference to a callable:

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_;
};

Obviously, this approach is not stateless, as I have to store the callbacks (member c_callbacks_) as passed to the C interface.

Is there a way to implement the wrapper class stateless, i. e. get rid of the member?

Please see https://onlinegdb.com/rkeh-UNX0U for the full code example.

Some background: The intention to make the wrapper stateless comes from the fact that the library behind the C interface may at some point dispose all added callbacks. Obviously this would lead to an ever growing list (member c_callbacks_) when cyclically adding callbacks and triggering the library to dispose them. How can I cope with such leak if the dispose action is not propagated over the C interface?

Aucun commentaire:

Enregistrer un commentaire