Frage

Ich habe ein sehr einfaches "Plug-in-System" als Teil eines statische Bibliothek implementiert. Jede „Plug-in“ implementiert die Unterstützung für ein anderes Bildformat, z.B. GIF, JPEG, etc .. Darüber hinaus habe ich eine Singleton (eine Klasse namens PluginManager), die eine Liste aller verfügbaren Plug-Ins hält.

Der schwierige Teil ist, dass ich mag die Plug-In deaktivieren / aktivieren durch Hinzufügen oder Entfernen ihrer Quelldateien aus der Projektdatei. Um dies zu erreichen, jeder Plug-in erstellt eine globale Variable (mit unterschiedlichen Namen) und registriert die Plug-in in dem Konstruktor dieser Klasse PluginManager.

So etwas wie dies für das JPEG-Format ...

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

  // plenty of other code
  ...
};

JPEGPlugin jpeg_instance;  // instantiate in global scope

Während jedoch diese perfekt in der Theorie funktioniert, versagt es, wenn an anderem Code diese statische Bibliothek verknüpft eine ausführbare Datei zu erstellen. Solange diese ausführbare Datei nicht das Plugin-Globals zugreift (wie jpeg_instance), wird der Linker sieht keine Verbindung (er ignoriert vollständig die Nebenwirkungen des Konstrukteurs) und den Code nicht in den endgültigen ausführbaren umfassen. Mit anderen Worten, ist die JPEG-Plug-in in dem letzten App nicht verfügbar ist.

Ich lief in die Probleme ein paar Mal im Laufe der Jahre, und ich suchte immer im Internet nach Lösungen. Jedes Mal, fand ich nur Seiten, die im Grunde sagen, dass es ein bekanntes Problem und dass ich damit leben.

Aber vielleicht jemand auf SO weiß, wie diese Arbeit zu machen?

War es hilfreich?

Lösung

Ich weiß nicht, ob dies eine Lösung für die Art und Weise, dieses Problem zu lösen, aber wir hatten ein ähnliches Problem mit statischer Registrierung eines Objekt Fabrik und in Visual Studio wir es gelöst, indem die Klassen mit __declspec (dllexport) beteiligt erklärt dies war notwendig, obwohl die beteiligten Bibliotheken waren nicht dlls. Aber ohne diese der Linker würde die nicht referenzierten Klassen weglassen.

Die Registry-Lösung wir ein wenig anders gearbeitet und Stapel nicht beteiligt zugeordneten Objekte. Ich hob Teile von CPP-Einheit, die auch ist, wo ich den __declspec Ansatz iirc entdeckt.

[Bearbeiten] Wir hatten auch von einem Teil des Codes, die Erklärung für die registrierte Klasse #include.

Andere Tipps

Da es sich um eine statische libary ist, sollten Sie überlegen, der Manager die Plugins registrieren zu müssen (statt der Plugins selbst Registrierung). Die Header-Datei kann einige preproc Symbole (dh JPEG_PLUGIN) definieren, der steuert, ob der Manager die Plugin Register auf der Grundlage der Einbeziehung der Kopfzeile:

#include "JpegPlugin.h"

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

JpegPlugin.h muss nicht unbedingt die Definition des JpegPlugin aufzunehmen. Es könnte so etwas wie diese:

#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

Dies ist ein Followup auf Harald Scheirich Antwort .

Ich habe einige Experimentieren getan, und es scheint, dass MSVC ++ 2005 der Release Mode (aber nicht Debug-Modus) auf der /OPT:REF Flagge an den Linker drehen wird, die nach dem LINK Dokumentation , verursacht keine unreferenced Symbole aus dem letzten EXE entfernt werden. Und die Webseite für __declspec(selectany) dass für globale Objekte Konstrukteuren, um anzuzeigen, scheint sind nicht als Verweis auf ein Objekt betrachtet (falsch IMHO, aber da haben Sie es). Also meine Vermutung ist, dass dieses Problem „geht weg“ für Debug-Builds - ist das richtig

Also, ich glaube Harald Vorschlag __declspec(dllexport) zu verwenden, ist eine bequeme Möglichkeit, das Symbol der Markierung als „referenziert“, weil es innerhalb des Quellcodes angegeben ist. Wenn aus irgendeinem Grund Sie exportieren das Symbol vermeiden wollte, ich vermute, Sie könnten das gleiche entweder mit dem /INCLUDE:mysymbol Linker Flagge oder die /OPT:REF Flag ausgeschaltet werden.

Bitte:

  1. fügen Sie das statische lib Projekt als Verweis auf das exe-Projekt
  2. setzen beide "Link Library Abhängigkeiten" und "Use Link Library Abhängigkeit als Eingänge", wie wahr.

Siehe dazu: config

Wenn „Use Link Library Abhängigkeit als Eingänge“ auf Ja, das Projektsystem Links in den OBJ-Dateien für .libs durch abhängige Projekte produziert. So sind alle Symbole keeped.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top