Ho un programma che carica un sacco di "addon" (diversi misuratori che misurano e visualizzano valori di sistema).
Gli "addons" sono "cresciuti" nel tempo e il codice di quali addon "attivare", e quanti di ciascuno (se c'è più di uno dei "dispositivi" nel sistema (cpu, interfacce di rete, ecc.) è codificato nel master. Ug (e ick).
Quello che voglio è che ogni addon-meter inserisca il suo nome e init-routine-addr in un array mentre vengono caricati. In questo momento, quali metri sono stati caricati sono fissi nel master in fase di compilazione. Quello che voglio è per la possibilità di caricamento dinamico, ma ancora più importante, per "estensioni di script" esterne (che potrebbe misurare "quasi tutto" e contare sul master da visualizzare i dati raccolti (come uno script che legge la temperatura esterna tramite alcuni dispositivi di terze parti). In altre parole, molto tempo dopo che il maestro è stato compilato, voglio fornire la possibilità di aggiungere altri misuratori di addon purché forniscano una specifica API callable.
Quindi, con l'aggiunta di una nuova estensione, ho bisogno di richiamare qualche routine init come carica che posizionerà il nuovo nome-contatore e la routine da chiamare in un class singleton che ha una matrice di nomi di estensione e i loro indirizzi di routine init (come in un'estensione caricata dinamicamente).
Quindi quando inizia l'esecuzione, ogni estensione avrà già "registrato" stesso con una lista centrale che il "maestro" può vedere e sapere cosa chiamare.
In perl, ho usato qualcosa in un "BEGIN {...} block" in estensioni caricate
per chiamare un Plug_Common->register("plugin name", \%Plugin_Description_Data);
, quindi, quando la routine principale è iniziata, nel registro del plugin dovrebbe apparire
ciò che era disponibile, dinamicamente, in fase di runtime.
La domanda è, come faccio a farlo in C ++?
Ho impostato la routine di registrazione, ma non ho idea di come avere le estensioni ottenere il proprio "nome e indirizzo" registrato prima dell'esecuzione del master principale. Teoricamente, poiché alcune estensioni potrebbero essere aggiunte tramite script molto tempo dopo è stato scritto il master principale - non sarebbe stato in grado di conoscerne i nomi in anticipo.
In cima alla mia testa, posso solo pensare a un file di testo statico "modificato dall'utente", che potrebbe essere in grado di avere il master, "in qualche modo (?!)" chiama ogni init init e la routine 'get_config' . Quindi posso sbarazzarmi di tutta la conoscenza "estensione / metro-specifica" dal maestro. Non mi piace l'idea del file di testo poiché è troppo soggetta a errori utente - avendo qualcosa che è in grado di chiamare automaticamente una funzione di registro mentre viene caricata, sembra molto meno probabile che abbia problemi come il file di configurazione statica fuori sincrono con quali estensioni possono essere utilizzate sul sistema.
Qualche idea? (Preferirei piuttosto non dover creare una copia di qualcosa come perl per gestire la "caricabilità" dinamica dei moduli ... per me sarebbe "brutto" ...
Sembra un po 'inaffidabile per il programma principale cercare di esaminarne alcuni tabella dei simboli in fase di esecuzione, in particolare con la strong digitazione di C ++. Continuo a venire con difetti praticamente in ogni metodo che penso. Triste. Qualcuno conosce un modo migliore? ;-) ...
Grazie mille!
Aggiornamento: Ho avuto un pensiero (beh più di uno, ma questo è un po 'non convenzionale, ma potrebbe funzionare) E se ognuno dei plug-in dichiarasse un puntatore condiviso a un elenco globale nel master?) Se i puntatori condivisi sono stati utilizzati a livello di modulo , quindi il 'conteggio degli usi' condiviso non dovrebbe essere incrementato quando i moduli sono stati caricati? ... hmmm ... Non so ancora come ottenere gli indirizzi dei moduli nell'array principale (senza che questi ottengano alcun tempo di esecuzione ), ma se riesco a capire un modo per un'istruzione di inizializzazione usando il parametro shared_ptr, poi dal momento che lo sto caricando come non-multithread (almeno a questo punto) se quel puntatore potrebbe essere sfruttato per incrementare e memorizzare l'indirizzo di una funzione init, in un array globale, potrebbe darmi la mia configurazione dinamica? In questo momento, l'unica cosa che so per certo è che i puntatori condivisi hanno un 'use_count' accessibile - il che mi aiuterebbe solo a determinare quanti plug-in sono stati registrati. Forse non c'è modo di farlo funzionare, ma solo un pensiero (alle 5:45 del mattino dopo che sono stato sveglio tutta la notte ... quindi, potrebbe essere completamente imperfetto e io proprio non lo vedo ancora ...; )) ... Comunque, ho pensato di aggiungere i miei ultimi pensieri; Per gli script, sto pensando di suddividere quel tipo di plugin in un gestore separato che dovrebbe leggere alcune configurazioni ... Non mi piace molto, ma isola quelle cose che non caricheranno l'ora di inizio del programma @ ... Qualcuno pensa che sia possibile sfruttare il puntatore condiviso per farlo?