2010-07-06 25 views
5

Ho un progetto MS C++ (chiamiamolo progetto A) che sto attualmente compilando come libreria statica (.lib). Definisce una variabile globale foo. Ho altri due progetti che compilano separatamente (li chiamano rispettivamente B e C) e collegano la libreria statica A in comune. Sia B che C sono dll che vengono caricati nello stesso processo. Vorrei condividere una singola istanza di foo da A tra B e C nello stesso processo: un singleton. Non sono sicuro di come realizzare il modello singleton qui con il progetto A poiché è compilato staticamente in B e C separatamente. Se dichiaro foo come extern sia in B che in C, finisco con diverse istanze in B e C. L'uso di un modello di classe standard semplice e semplice con un metodo getInstance statico genera due istanze statiche foo.Variabile globale condivisa nella libreria statica C++

Esiste un modo per ottenere ciò mentre il progetto A è compilato staticamente in B e C? O devo rendere A una DLL?

+0

* "Se dichiaro foo come extern sia in B che in C, finisco con diverse istanze in B e C." * - è proprio vero? –

+0

Sembra vero: è il comportamento che osservo quando passo il programma mentre eseguo il debug. Vedo il costruttore per foo chiamato due volte e gli indirizzi delle variabili extern g_Foo sono diversi nei due moduli B e C. Non dovrebbe essere così? – Zach

+0

possibile duplicato di [Come implementare la variabile globale del processo in C++?] (Http://stackoverflow.com/questions/669989/how-to-implement-process-global-variable-in-c) – Zach

risposta

4

Sì, è necessario creare A una DLL condivisa, oppure definirla come esterna in B e C e collegare tutti e tre in modo statico.

+0

Puoi approfondire cosa intendi per "collegare tutti e tre staticamente"? Attualmente sto collegando A staticamente sia in B che in C e dichiarando foo extern in B e C, ma alla fine mi ritrovo con più definizioni di foo in runtime. Penso che tu stia dicendo che avrei bisogno di collegare staticamente A e B in C (o A e C staticamente in B), o collegare staticamente A, B e C in un'altra libreria. È esatto? Grazie! – Zach

+0

L'ultimo, tranne che sostituisce "un'altra libreria" con "l'eseguibile finale". Non collegare nessuna delle librerie insieme. Invece, collega A, B e C staticamente con il tuo eseguibile finale. Tutti i simboli da A usati in B o C dovrebbero essere dichiarati extern in B e C, ma non definiti. Se colleghi A, B e C in un'altra libreria condivisa, devi solo assicurarti che questa libreria incapsuli il singleton da A, perché se A è collegato staticamente all'eseguibile e l'eseguibile accede direttamente ai dati statici di A, otterrà una copia diversa dalla lib. –

2

No, non sono condivisi.

Da Richter di 'Windows tramite C/C++' (P583):

Quando uno processo di mapping di un file di immagine DLL nel suo spazio spazio degli indirizzi, il sistema crea istanze del globale e dati statici variabile pure.

Quindi, se è necessario condividere una risorsa tra più eseguibili, sarà necessario creare un oggetto kernel condiviso di qualche tipo. Vorrei suggerire la creazione di una mappatura file chiamato, che è possibile utilizzare per leggere e scrivere dai processi separati

+0

La tua osservazione è corretta in generale, ma hai supervisionato una richiesta importante dell'OP: "* Sia B che C sono dll che vengono caricati ** nello stesso processo **. *" Quindi con DLL sarebbe condiviso. Il problema qui è il collegamento statico. – Christophe

+0

A proposito, la condivisione tra i processi può essere facilmente raggiunta come spiegato qui: http://stackoverflow.com/a/7705793/3723423 – Christophe

0

ottengo questo problema actualy (con adeguate esclusione Mutex, naturalmente.):

Ho A .EXE collegato con B.LIB. Ho C.DLL anche collegato con B.LIB.

Come si può vedere, questi due programmi sono collegati con B.LIB

Ora, quando richiesto, l'a.exe andare caricare C.dll. Dopo aver caricato, A.EXE e C.DLL hanno ciascuno separato B.LIB per codice e dati

Il problema è possibile avere un "fantom" B.LIB collegato con C.DLL per utilizzare il già caricato in a.exe?

Penso di no. È una limitazione da Window. In Linux puoi, se ricordo correttamente. Questo è stato considerato dall'opzione -fPic di GCC. Ma non sono sicuro.

La soluzione per condividere dati globali/statici memorizzati in B.LIB con A.EXE e C.DLL consiste nell'utilizzare classi/interfacce condivise. L'interfaccia di invio A.EXE a C.DLL con un puntatore di dati/interfaccia al B.LIB memorizzato in A.EXE.

In altre parole, se il C.DLL deve impostare/stato condiviso di una variabile statica in B.LIB, il file A.EXE deve inizializzare C.DLL con l'interfaccia per consentire lo scambio di dati con B.LIB in a.exe.

In tutti i casi, il B.LIB memorizzata in C.dll continuano a gonfiare il programma globale a causa del codice duplicato B.LIB in a.exe e C.dll

Per ridurre il gonfiore globale, devi dividere il tuo A.LIB in più D.DLL, E.DLL caricate da A.EXE e trasmesse attraverso l'interfaccia a C.DLL

Per ridurre a zero il codice gonfiato, è necessario utilizzare il metodo dell'interfaccia indipendente completa.

Problemi correlati