Loke
Loke

Reputation: 19

How to call a C++ member method from a C callback function with PipeWire

I am trying to adapt this PipeWire example for use with C++, as I need to carry out various processing in a C++ method. But I am not sure how I can call a C++ member method from the static callback function, i.e. from:

static void on_process(void *userdata, struct spa_io_position *position)

Any suggestions?

Upvotes: 0

Views: 143

Answers (2)

wohlstad
wohlstad

Reputation: 29159

You can do the following:

  1. Use either a global function, or a static method of your class as a callback. Each has advantages and disadvantages:
    • A static method has the advantage of packing everything together.
    • A global function has the advantage of not cluttering the class but requires to make the callback method public or the function a friend.
  2. When you register the callback, pass the addess of the class instance (this pointer if you are inside a method) as the userdata.
  3. In your static/global callback cast userdata back into a pointer to your class instance.
  4. Use the casted pointer to call a method of your class (casted_pointer->...).

Pseudo code (static method variant):

class A
{
    void register_me_for_on_process()
    {
        void * user_data = this;
        register_on_process(on_process_static, user_data, ...);
    }
    
    // Static callback for registering with the API:
    static void on_process_static(void *userdata, ...)
    {
        A * pThis = reinterpret_cast<A*>(userdata);
        pThis->on_process(...);
    }

    // Callback:
    void on_process(...)
    {
    }
};

The global function variant is very similar - just take the on_process_static method out of the class, and make the on_process method public (or make on_process_static a friend).

Upvotes: 3

KamilCuk
KamilCuk

Reputation: 141748

This is what userdata is for. For user data.

struct UserData {
   void on_process(struct spa_io_position *position) { /* blabla */ }
};

static void on_process(void *userdata, struct spa_io_position *position)
{
        UserData *ud = static_cast<UserData*>(userdata);
        ud->on_process(position);
}
 
static const struct pw_filter_events filter_events = {
        PW_VERSION_FILTER_EVENTS,
        .process = on_process,
};

int main(int argc, char *argv[])
{
        struct UserData ud;
        pw_filter_new_simple(blabla, static_cast<void*>(&ud));
}

Upvotes: 2

Related Questions