Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind class method and pass it as function pointer

I would like to pass my class method as an argument to a (third-party) function (listner - that cannot be changed) that accepts a function pointer and a void*. Following is an example:

#include <functional>

typedef void(*pfnc) (void*);

struct Foo
{
    static void static_foo(void*)
    {
    }

    void foo(void*)
    {
    }

    void listner(pfnc f, void* p)
    {
       f(p);
    }

    void test()
    {
        listner(static_foo); // works with static method

        auto f = [](void*) {};
        listner(f); // works with lambda

        std::function<void(void*)> stdf = std::bind(&Foo::foo, this, std::placeholders::_1);
        listner(stdf);  // does not compile with not static method
    }
};

Unfortunately my solution does not compile. What do I have to change?

like image 597
Nick Avatar asked Oct 30 '22 00:10

Nick


1 Answers

From the look of the callback signal, the listener API takes a pointer to void as 'user defined data'. You can pass this as the data and a small stateless proxy function to route to the handler on Foo:

typedef void(*pfnc) (void*);

struct Foo
{
    static void static_foo(void*)
    {
    }

    void foo()
    {
    }

    void listner(pfnc f, void* user_data)
    {

        // eventually calls
        f(user_data);
    }

    void test()
    {
        listner(static_foo, nullptr); // works with static method

        auto f = [](void*) {
        };
        listner(f, nullptr); // works with lambda

        listner([](void* pv)
        {
            reinterpret_cast<Foo*>(pv)->foo();
        }, this);
    }

};
like image 172
Richard Hodges Avatar answered Nov 11 '22 18:11

Richard Hodges