Domanda

ho implementato un "sistema di plug-in" molto di base come parte di un libreria statica . Ogni "plug-in" implementa il supporto per uno specifico formato di immagine, ad esempio GIF, JPEG, ecc .. Inoltre, ho un Singleton (una classe chiamata PluginManager) che mantiene un elenco di tutti i plug-in disponibili.

La parte difficile è che voglio per abilitare / disabilitare i plug-in, aggiungendo o rimuovendo i file di origine dal file di progetto. Per raggiungere questo obiettivo, ogni plug-in crea una variabile globale (con nomi diversi) e registra il plug-in nel costruttore di quella classe al jpeg_instance.

qualcosa di simile per il formato JPEG ...

struct JPEGPlugin
{
  // constructor will register plugin
  JPEGPlugin()
  {
    PluginManager::Singleton().RegisterPlugin(this);
  }

  // plenty of other code
  ...
};

JPEGPlugin jpeg_instance;  // instantiate in global scope

Tuttavia, mentre questo funziona perfettamente nella teoria, non riesce quando si collegano questa libreria statica per altro codice per costruire un eseguibile. Finché questo eseguibile non accedere alle variabili globali di plugin (come <=>), il linker non vede un collegamento (che ignora completamente gli effetti collaterali del costruttore) e non include il codice nel file eseguibile finale. In altre parole, il plug-in JPEG non è disponibile in App finale.

Mi sono imbattuto in problemi un paio di volte nel corso degli anni, e ho sempre cercato la rete per le soluzioni. Ogni volta, ho appena scoperto le pagine che in sostanza dicono che si tratta di un problema noto e che devo vivere con esso.

Ma forse qualcuno conosce così come fare questo lavoro?

È stato utile?

Soluzione

Non so se questo una soluzione per il modo in cui avete risolto questo problema, ma abbiamo avuto un problema simile con la registrazione statica di una fabbrica di oggetto e in Visual Studio abbiamo risolto dichiarando le classi coinvolte con __declspec (dllexport) questo era necessario anche se le biblioteche coinvolte non erano DLL. Ma senza questo il linker potrebbe omettere le classi non si fa riferimento.

La soluzione registro abbiamo lavorato un po 'diverso e non ha comportato Pila allocato oggetti. Sollevai parti da CPP-unità, che è anche il luogo dove ho scoperto l'approccio IIRC __declspec.

[modifica] Abbiamo anche dovuto #include la dichiarazione per la classe registrato da qualche parte del codice.

Altri suggerimenti

Dato che si tratta di un libary statica, si potrebbe considerare di registrare il manager dei plugin (al posto dei plugin che registrano stessi). Il file di intestazione può definire qualche simbolo preproc (cioè JPEG_PLUGIN) che controlla se il direttore registra il plugin basata sull'inclusione di intestazione:

#include "JpegPlugin.h"

void PluginManager::RegisterPlugins()
{
#idef JPEG_PLUGIN
    RegisterPlugin(&jpeg_instance);
#endif
}

JpegPlugin.h non deve necessariamente includere la definizione del JpegPlugin. Potrebbe essere qualcosa di simile:

#ifndef JPEG_PLUGIN_HEADER
#define JPEG_PLUGIN_HEADER

#if 0 // change this to 1 to use the plugin
#define JPEG_PLUGIN
#include "Jpeg_PluginCls.h"
#endif

#endif

Questo è un follow-up a di Harald Scheirich risposta .

Ho fatto alcuni esperimenti, e sembra che MSVC ++ 2005 di modalità di rilascio (ma non la modalità di debug) si accende la /OPT:REF bandiera per il linker, che secondo il documentazione LINK , farà sì che tutti i simboli senza il riferimento per essere rimosso dal file EXE finale. E, la pagina web per __declspec(selectany) sembra indicare che per i costruttori oggetti globali non sono considerati come riferimenti a un oggetto (in modo non corretto IMHO, ma il gioco è fatto). Quindi la mia ipotesi è che questo problema "va via" per il build di debug -? È corretto

Quindi, penso che il suggerimento di Harald di utilizzare __declspec(dllexport) è un modo conveniente di segnare il simbolo come "riferimento", perché è specificato all'interno del codice sorgente. Se per qualche motivo si voleva evitare di esportare il simbolo, ho il sospetto che si potrebbe ottenere lo stesso sia usando il /INCLUDE:mysymbol linker bandiera , o spegnere il <=> bandiera.

  1. aggiungere il progetto lib statica come un riferimento al progetto exe
  2. impostare entrambi di "dipendenze libreria di collegamento" e "Usa Link Library dipendenza come ingressi" come vero.

Vedere questo: config

Quando "libreria di dipendenza Usa collegamento come ingressi" è impostata su Sì, i collegamenti del sistema progetto nei file obj per .libs prodotti dai progetti dipendenti. Quindi, tutti i simboli, tutt'oggi conservati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top