C++ – Library IO: Use Interface Classes or Callbacks?

ccallbacksinterfaceslibraries

I'm building a smallish library (few kLOC) which processes stream data in C++. From the streamed data (comes in packets) the library compiles a database piece by piece and naturally has to convey that information back to the host application.

Since this is my first library I'm unsure how to proceed with the API/Interface. AFAIK I have the choice between using a CPP "Interface" or C-style callbacks. This question is not just related to the programming aspect but also to the aspect of managing the library API between versions:

Why would I use an Interface?

  • Interfaces are declared once and API changes are directly reflected in that class
  • It is impossible to forget a method or an event as the library just doesn't compile
  • It is "cleaner" C++ than C-style Callbacks
  • I'm sure what I'm doing within the library and, hide "maybe complex" stuff behind a return value

Using an Interface

class InterfaceClass {

public: 

    virtual bool isDataBlockComplete(...) = 0;
    virtual bool isDataBaseUpdated(...) = 0;
    virtual bool hasEventCompleted(...) = 0;
    [..]
}


/* User code */

class SomeClass : InterfaceClass { [..] }

bool SomeClass::hasEventCompleted(...){ /* check */ }

SomeClass *instance = new SomeClass();

InterfaceClass *instance = new InterfaceClass();

if(instance->hasEventCompleted) [..]

for(i = 0; i < instance->getQueueSize(); i++ ) [..]

Why would I use C-style Callbacks?

  • They can be registered and updated during runtime
  • Events can be "subscribed" this way
  • Helps in providing a C-Wrapper later on
  • It's way faster because less code has to be written & tested by me

Using Callbacks

class InterfaceClass {

public:

    registerCallback( void *f, tEvent event);
    deregisterCallback(tEvent event);
}


/* User code */

void myfunc(){ .. }

instance->registerCallback(&myfunc, SOME_EVENT);

/* Gets called by the governor / observer of library */

So this is not a question of preferability, but which "style" to be used for a library. I didn't find anything on the net (it all seems to revolve around the technical aspects of using virtual abstract classes or on how to implement callbacks but no one actually discusses what I've asked above) despite a thorough search (maybe wrong choice of word combinations).

Which style is better suited for such kind of library and why?
How do "professional" libraries communicate with the main applications? (Maybe too broad for SE, but trying anyway :))

Best Answer

I would suggest avoiding the use of C-style callbacks in C++ code. C++ provides an equivalent idiom that gives better type-safety, is easier to read (at least for most C++ developers), and may provide the compiler better chances to optimize the code. It also allows the use of lambda functions to define the behaviour at call site, which you can't achieve using function pointers. This is the std::function template class in the <functional> header.

Using this, your code might look like:

class InterfaceClass {

public:
   registerCallback(std::function<void(MyEvent)> callback, tEvent event);
   deregisterCallback(tEvent event);
};

instance->registerCallback ([] (MyEvent evt) { 
                               /* do something here */ 
                            }, SOME_EVENT);
Related Topic