Implementing callback (for C library) as pure virtual in C++ abstract class

后端 未结 2 1766
滥情空心
滥情空心 2021-01-25 17:38

I ran into a problem when using a C audio library (PortAudio built with ASIO SDK, but this isn\'t really relevant to this question; the technical details would only hinder m

相关标签:
2条回答
  • 2021-01-25 18:04

    Your code is oversimplified. In real world both the "library function" and the callback will have a void* "user data" parameter. You can pass a pointer to your class instance into "user data" of the "library function" and it will be forwarded into the callback where you can use that pointer to access the object.

    class CallbackImplBase {
    public:
       virtual void CallbackImpl() = 0;
       static void CallbackToPass( void* userData )
       {
           static_cast<CallbackImplBase*>(userData)->CallbackImpl();           
       }
    };
    
    class ActualCallbackImpl : public CallbackImplBase {
         void CallbackImpl() { //implemented here }
    };
    
    ActualCallbackImpl callback;
    callLibraryFunction( params,
       &CallbackImplBase::CallbackToPass, static_cast<CallbackImplBase*>( &callback ) );
    

    Note the static_cast near the last parameter of the "library function" call. You won't need it unless you have multiple inheritance, it's still there anyway.

    0 讨论(0)
  • 2021-01-25 18:14

    As far as I can see, the callbacks in PortAudio, such as this one, take a void* argument for passing user data to them. You can use this to call member functions by passing a class pointer as user data, and writing a small static or non-member function to register as the C-compatible callback. For example:

    // C library function
    typedef void (*c_library_callback)(void * user_data);
    void c_library_start_stuff(c_library_callback, void * user_data);
    
    // C++ class using it
    class audio_thing {
    public:
        virtual ~audio_thing() {} // Better have one of these in an abstract class
    
        void start_stuff() {
            c_library_start_stuff(&audio_thing::static_callback, this);
        }
    private:
        // C-compatible callback forwards to the implementation
        static void static_callback(void * thing) {
            static_cast<audio_thing*>(thing)->callback();
        }
    
        // Derived classes implement the callback behaviour
        virtual void callback() = 0;
    };
    
    0 讨论(0)
提交回复
热议问题