Plugin-System: über DLLs, LIBs und Klassen(-instanzen)
-
Hallo...
Beim erstellen eines Plugin-Systems sind mir verschiedene Probleme aufgefallen, die ich bisher nicht so recht lösen konnte.Stand der Dinge
Das Projekt ist ein Serverplugin für Counter-Strike: Source. Das Serverplugin selber (ab nun Projekt) soll verschiedene Klassen und Interfaces zur Verfügung stellen, zu einem einfachen Zweck: Das Projekt soll es ermöglichen, schnell und einfach Addons für das Projekt zu entwickeln, welche dann wiederum auf das Spiel zugreifen. Das heißt, es gibt folgende Abfolge (Beispiel):Spiel meldet Event -> Projekt registriert dies -> Projekt leitet Event an alle Addons weiter. Ich möchte es den Addonautoren so einfach wie möglich machen, deshalb soll das ganze auch gut geplant sein. Am besten wäre es, wenn die Autoren "nur noch" dieProjekt.hppeinbinden müssen, um dann problemlos Addons zu erstellen.Was ich nun realisieren möchte
Ich möchte realisieren, dass die Addonautoren keine eigenen Implementationen schreiben müssen. Das heißt, dass das Projekt alle Implementationen bereitstellt und nur noch die Headerdatei(en) an die Addonautoren weitergeben soll. Ich habe das bereits versucht, und diesen Artikel gefunden, so richtig weiterhelfen tut er mir aber dennoch nicht.Was möglich sein sollte - Szenario 1
Der Addonautor inkludiertProjekt.hppund sollte mit kürzestem Code bereits erfolge erzielen. Beispiel:#include "Projekt.hpp" PROJEKT_PUBLISH_ADDON(Addon); // mögliche Implementierung dieses Makros könnte ungefähr so aussehen: // Addon AddonInstance(); // extern "C" __declspec(dllexport) IAddon *GetAddonInstance() // { // return &AddonInstance; // } // IProjekt *NL = NULL; // extern "C" __declspec(dllexport) void SetAddonInstance(IProjekt *pNL) // { // NL = pNL; // } class Addon : public IAddon { public: virtual void OnLoad() { NL->Output->ConsolePrint("Addon geladen!"); } virtual void OnUnload() { NL->Output->ConsolePrint("Good bye!"); } };NList vom TypIProjekt. Die Instanz vonIProjektsoll nun alle möglichen Subklassen beinhalten.IProjektkönnte so aussehen:class IProjekt { public: IProjekt() // Diese Funktion soll nur einmal (vom Projekt selber) aufgerufen werden, am besten sollten die Addonautoren die Implementation nicht zu Gesicht bekommen { this->Output = new Output; //this->... = new ...; } IOutput *Output; //I... *...; };Zur Frage: Wie muss ich das ganze machen, damit das auch so funktioniert?
Was möglich sein sollte - Szenario 2
Es sollte außerdem möglich sein, eigene Instanzen von Klassen zu erstellen (im Addon). Beispiel:class Addon : public IAddon { public: // von oben virtual void OnTick() { IPlayer *Player = NL->Players->FindByUserID(6); IUserMessage UserMessage(); UserMessage.WriteByte(0); UserMessage.WriteString("bla"); Player->SendUserMessage(UserMessage); // Signatur von SendUserMessage: // virtual void SendUserMessage(const IUserMessage &UserMessage); } };Wie genau kriege ich es nun hin, dass die Addonautoren auch Instanzen von IUserMessage erstellen können, ohne dass diese die Implementation machen müssen (sie sollen also nur die Headerdateien bekommen)?
Eine weitere Frage: Ist es so sinnvoll, oder wäre es designtechnisch besser, wenn manIUserMessage::Send(const IPlayer &Player)aufruft?Bin echt dankbar für jegliche Art von Hilfe!
Gruß