C programmazione di back-end di archiviazione multipli

4

Sto avviando un progetto parallelo in C che richiede che più backend di archiviazione siano guidati da una particolare logica. Questi back-end di archiviazione sarebbero collegati ciascuno con la decisione di quale utilizzare per l'utilizzo specificato in fase di runtime.

Quindi, ad esempio, se invoco il mio programma con un set di parametri, eseguirò le operazioni in memoria, ma se modifico la configurazione del programma, scriverebbe su disco.

L'idea di fondo è che ogni back-end di storage dovrebbe implementare lo stesso protocollo. In altre parole, la logica per le operazioni di esecuzione dovrebbe avere bisogno di sapere su quale back-end funziona.

Attualmente il modo in cui ho pensato di fornire questa indiretta è di avere un struct di puntatori di funzione con la logica che chiama questi puntatori di funzione. Essenzialmente la struttura contiene tutte le operazioni necessarie per implementare la logica di livello superiore E.g.

struct Context {
    void (* doPartOfDoOp)(void)
    int (* getResult)(void); 
}

//logic.h
void doOp(Context * context) {
    //bunch of stuff
    context->doPartOfDoOp();
}

int getResult(Context * context) {
    //bunch of stuff
    return context->getResult();
} 

Le mie domande sono se questo modo di risolvere il problema è comprensibile a un programmatore C? Sono uno sviluppatore Java per mestiere, ma mi piace usare C / ++. Essenzialmente la struttura Context fornisce un'interfaccia come livello di riferimento indiretto. Tuttavia mi piacerebbe sapere se esiste un modo più idiomatico per raggiungere questo obiettivo.

    
posta ahjmorton 18.10.2013 - 22:37
fonte

1 risposta

3

Sì, un programmatore C esperto avrebbe certamente compreso tali costrutti. L'uso dei puntatori di funzione è praticamente l'unico modo in cui si ha in C per selezionare in fase di esecuzione quale di un insieme di funzioni da eseguire.

Ans memorizzando i puntatori di funzione in una struttura fornisce un segnale molto chiaro che tali funzioni appartengono insieme ed è un modo molto comune di emulare metodi / funzioni membro in C.

Una modifica che consiglierei è di passare la struttura Context anche come 'questo puntatore' ai puntatori di funzione, in questo modo:

struct Context {
    void (* doPartOfDoOp)(struct Context*)
    int (* getResult)(struct Context*); 
};

//logic.h
void doOp(Context * context) {
    //bunch of stuff
    context->doPartOfDoOp(context);
}

int getResult(Context * context) {
    //bunch of stuff
    return context->getResult(context);
}

In C, se hai un puntatore al primo membro di una struct, puoi lanciare quel puntatore al tipo struct stesso e usarlo per accedere agli altri membri. Questo ti permette di costruire una sorta di albero ereditario e rende possibile dare le "variabili membro" dei tuoi back-end, come questo:

struct FileBackend {
    struct Context interface;
    FILE* file;
}

void doPartOfDoOpFileBackend(struct Context* context)
{
    struct FileBackend* this = (struct FileBackend)context;
    // do stuff, accessing the file through this->file.
}
    
risposta data 19.10.2013 - 11:05
fonte

Leggi altre domande sui tag