Naja, gibt mehrere Stufen von Pluginkonzepten.
Die einfachste iss die rohe aber optinale Dll. iss sie vorhanden, wird ne funktion freigeschalten, wenn nicht, funktioniert der Rest der applikation trotzdem noch.
Nen vollstaendiges Plugin geht natuerlich weiter. besteht aus 2 teilen. nen statischer Manager für die Applikation selbst, der die eigentlichen plugins verwaltet, und die Plugins selbst.
Wir nutzen hier das konzept der Pluginfactory. Das heist, jedes Plugin hat seine eigene Pluginfactory. diese Factory haelt (verwaltungsdaten)daten über das plugin und kann es halt erzeugen. Weiterhin bestimmt die Factory ob ein plugin pro prozess multiinstanziable iss oder nicht (singleton)
Funktionieren tut das folgendermassen.
Es gibt eine IPluginFactory Schnittstelle. diese enthaelt die daten über das Plugin sowei den "Typ" bzw die Schnittstellen, die das Plugin unterstuetzt. weiterhin noch author ne beschreibung etc.
jede PluginDll kann ein oder mehrere Pluginfactories haben.
die dll selber hat genau 2 exportierte funktionen, size_t getPluginFactoryCount() und IPluginFactory * getPluginFactory(size_t index)
So checkt der PluginManager, ob die dll nen plugin ist, in dem er mit getProcAdress("getPluginFactory") und getProcAdress("getPluginFactoryCount") gueltige funktionspointer fuer die funktionen bekommt. Wenn nicht, iss die dll fuer ihn kein plugin.
Die Factories selber sind quasi "global" in der Dll, werden damit sofort beim erzeugen angelegt. Da die factories nur meta informationen enthalten, werden die auch flott erzeugt. Wichtig iss halt nur, das die pluginfactory allein schon alle daten haelt, die die Application braucht um entscheiden zu koennen ob sie ein plugin nutzen kann / muss oder nicht.
Nichts iss schlimmer als wenn man im vorhinaus das Plugin erzeugen muss um an daten zu kommen, und die App dann anhand der Daten entscheidet neee, brauch ich doch ned, ich entlad das mal wieder.
Die Pluginfactory erzeugt dann die Plugins selber.
Die Plugins sind alle von IPlugin abgeleitet. Damit hat man ein haendle zum verwalten aller plugins. Jede factory kann damit Ihr (und damit nur einen typ) erzeugen.
Sieht bei uns so aus:
IPlugin * IPluginFacotory::createPlugin()
Weiterhin unterscheidet die factory, ob sie ein neues plugin erzeugt, oder nen zeiger (referenzgezaehlt) auf ein scho vorhandenes Plugin rausgibt.
Zu jedem creaete gehoert dann natuerlich das zugehoerige void IPluginFacotory::releasePlugin(IPlugin * P)
das Plugin selber kann ned viel.
Wichtig: die eigentlichen typisierten arbeitsschnittstellen der Plugins sind nicht von IPlugin abgeleitet. Und ein plugin kann mehrere (nicht miteinander verwandte) schnittstellen unetrstuetzen.
Beispielsweisse wenn man ein Plugin fuer einen Converter hat, die Schnittstelle dazu IConvert ist, kommt man bei uns ueber eine "cast" methode drauf. das cast iss syntaktisch schlecht gewaehlt, besser sollte es "queryInterface" heissen. aber dinge sind halt gewachsen.
die Signatur ist:
void * IPlugin::cast(const char * InterfaceName, unsigned int InterfaceVersion);
jedes Interface bekommt bei uns 2 statische memberfunktionen, die den namen des interfaces rausruecken sowie die Verion der schnittstelle,
sieht quasi ungefaehr so aus:
Code: Alles auswählen
const char * const ICONVERT_INTERFACENAME = "IConvert";
const unsigend int ICONVERT_INTERFACEVERSION = 0x00010012;
class IConvert
{
public:
static const char * InterfaceName() {return ICONVERT_INTERFACENAME;}
static unsigned int InterfaceVersion() {return ICONVERT_INTERFACEVERSION;}
/// ....
/// hier dann die abstrakten funktionen die das interface so braucht.
}
damit laesst sich das cast recht bequem aufrufen:
Code: Alles auswählen
IConvert * pConverter = reinterpret_cast<IConvert *>(pPlugin->cast(IConvert::InterfaceName(),IConvert::InterfaceVersion()));
Das wiederum laesst sich super templatisieren ^^
Der PluginManager selber iss ne lib die man in ne application einbindet. dem gibt man ein oder mehrere verzeichnisse, daraus laed er sich alle plugins und baut ne interface / type map auf.
den Manager fragt man dann nach allen PluginFactories fuer eine bestimmte schnittstelle oder einen bestimmten typ und natuerlich Version ab ... und die app laesst dann den user entscheiden, welches plugin verwendet wird, falls notwendig.
oder es ist ein mechanismuss dahinter, der selber das beste plugin rausfindet (bei dateiconverter z.b. probt er durch).
Wird das plugin dann gebraucht, wird es erst dann aus dern factory erzeugt.
So machen wir es, wobei wir ziemlich extensiv plugins auf c++ basis verwenden.
vielleicht hilft dir das ...
gibt auch andere techniken ... com basiert z.b.
Ciao ...