c++c++11lambdastd-function

How to pass a std::function with capture through a C API?


I have a C API that is a queue used to pass messages between threads. I want to pass a std::function<void()> through it, but to do that, I need to degrade it to a POD chunk of data of constant length.

The std::function will be mostly from C++11 lambdas and will capture by reference or copy. I can use the heap from both sides of the C-queue.

The queue itself is a FreeRTOS queue and this is in embedded. There is some discussion about passing C++ish things through the queue on their forums. It mostly says it's ok if it's a POD or is trivially constructable.

Currently I'm passing around struct { void (*fp)(void*); void* context; }, and execute it as received.fp(received.context); but I'd like something a bit better in terms of readability without sacrificing much more resources. (EDIT: expanded on current use and needs)

Any idea how to do this?


Solution

  • I don't know much about FreeRTOS, but with your requirements, you should be able to use a pointer to your std::function object (either heap-allocated or a pointer to a non-heap allocated object if its lifetime permits) -- all raw pointers are POD, even if they point to C++ objects.

    Here's a quick example of using a pointer to a bound std::function allocated on the stack:

    std::function<void()> produce(int value)
    {
        return [value]() {
            std::cout << "Value = " << value << std::endl;
        };
    }
    
    void consume(std::function<void()> *callback)
    {
        (*callback)();
    }
    
    int main()
    {
        auto cb = produce(42);
        consume(&cb);
    
        return 0;
    }