Library IO: utilizzare classi di interfaccia o callback?

4

Sto costruendo una libreria piccola (pochi kLOC) che elabora i dati di streaming in C ++. Dai dati in streaming (inclusi nei pacchetti) la libreria compila un database pezzo dopo pezzo e, naturalmente, deve riportare tali informazioni all'applicazione host.

Poiché questa è la mia prima libreria, non sono sicuro di come procedere con l'interfaccia API. AFAIK Ho la scelta tra l'utilizzo di un "Interfaccia" CPP o callback in stile C. Questa domanda non riguarda solo l'aspetto della programmazione, ma anche l'aspetto della gestione dell'API della libreria tra le versioni:

Perché dovrei usare un'interfaccia?

  • Le interfacce vengono dichiarate una volta e le modifiche alle API si riflettono direttamente in quella classe
  • È impossibile dimenticare un metodo o un evento dato che la libreria non viene compilata
  • È un C ++ "più pulito" rispetto ai callback in stile C
  • Sono sicuro di quello che sto facendo all'interno della libreria e nascondo cose "forse complesse" dietro un valore di ritorno

Utilizzo di un'interfaccia

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++ ) [..]

Perché dovrei usare callback in stile C?

  • Possono essere registrati e aggiornati durante il runtime
  • Gli eventi possono essere "sottoscritti" in questo modo
  • Aiuta a fornire un C-wrapper in un secondo momento
  • È molto più veloce perché è necessario scrivere meno codice e amp; testato da me

Uso di callback

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 */

Quindi questa non è una questione di preferibilità, ma quale "stile" da utilizzare per una biblioteca. Non ho trovato nulla in rete (tutto sembra ruotare attorno agli aspetti tecnici dell'uso di classi astratte virtuali o su come implementare i callback ma nessuno in realtà discute di quello che ho chiesto sopra) nonostante una ricerca approfondita (forse una scelta sbagliata di combinazioni di parole).

Quale stile è più adatto per questo tipo di libreria e perché? In che modo le librerie "professionali" comunicano con le applicazioni principali? (Forse troppo ampio per SE, ma provando comunque:))

    
posta Jan Krüger 15.12.2016 - 11:53
fonte

2 risposte

1

Suggerirei di evitare l'uso di callback in stile C nel codice C ++. C ++ fornisce un idioma equivalente che offre una migliore sicurezza del tipo, è più facile da leggere (almeno per la maggior parte degli sviluppatori C ++) e potrebbe fornire al compilatore maggiori possibilità di ottimizzare il codice. Consente inoltre l'uso delle funzioni lambda per definire il comportamento sul sito di chiamata, che non è possibile ottenere utilizzando i puntatori di funzione. Questa è la classe template std::function nell'intestazione <functional> .

Usando questo, il tuo codice potrebbe essere simile a:

class InterfaceClass {

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

instance->registerCallback ([] (MyEvent evt) { 
                               /* do something here */ 
                            }, SOME_EVENT);
    
risposta data 16.12.2016 - 17:59
fonte
3

Ti suggerisco di prendere in considerazione schema osservatore . È possibile registrare e annullare la registrazione dei listener di eventi (osservatori) in fase di esecuzione.

Se si desidera utilizzare una funzione C legacy come callback, si crea una classe observer wrapper che delegherà le notifiche degli eventi a tale callback.     
risposta data 15.12.2016 - 15:47
fonte

Leggi altre domande sui tag