2008-12-09 3 views
12

Also habe ich eine Anwendung, die stark auf der QT-API basiert, die das QPlugin-System verwendet. Es ist ziemlich einfach zu verwenden, Sie definieren eine Klasse, die von einer Schnittstelle erbt und wenn das Plugin geladen wird, erhalten Sie eine Instanz dieser Klasse. Am Ende wird es auf ein dlopen/dlsym oder LoadLibrary/GetProcAddress herunterkochen, was auch immer für das Betriebssystem geeignet ist. Ich habe keine Probleme hier funktioniert alles wie erwartet.Plugin API Design

Also, auf das Problem. Es gibt ein Los der Funktionalität, die ein Plugin beinhaltet, das sich auf Daten/Funktionen beziehen muss, die von der Hauptanwendung bereitgestellt werden. Zum Beispiel hat meine Anwendung eine GUI, also habe ich in meiner Anwendung eine "plugin::v1::gui" -Funktion, die eine QWidget * zurückgibt. Wenn ich möchte, dass ein Plug-in in der Lage ist, Dinge zu meiner Benutzeroberfläche hinzuzufügen, oder sogar den Dialog zu einem Kind meiner Benutzeroberfläche zu machen, benötigt es einen Zeiger darauf.

Ich begann die Entwicklung unter Linux und stieß schnell auf die Tatsache, dass der Loader standardmäßig nicht aufgelöste Symbole in geteilten Objekten mit denen aus der Anwendung, die ihn laden, füllt. Kein Problem, einfache Lösung. füge "-rdynamic" zu meinen Flaggen hinzu und gehe weiter. Das funktioniert gut.

Jetzt habe ich entdeckt, dass es keine äquivalent unter Windows zu sein scheint :(. Also, was ist eine gute Lösung?

Bisher ist die beste, die ich habe kommen mit einer Struktur I füllen Sie in meiner Hauptanwendung, die Zeiger auf jedes Objekt/Funktion hat ein Plug-in möglicherweise kümmern dann an die Funktion "init()" Plugins und jetzt hat es richtige Hinweise auf alles, aber es ist eine lästige Lösung, da jetzt muss ich machen Änderungen an mehreren Stellen, wenn ich etwas hinzufüge.

Gibt es eine bessere Lösung? Wie hat die SO-Community damit umgegangen?

Antwort

4

Erstellen Sie eine Reihe von Schnittstellen für die wichtigsten Interaktionsobjekte, die von Ihrer Anwendung bereitgestellt werden, und erstellen Sie sie in einer eigenen lib/dll und implementieren Sie diese Schnittstellen für Klassen in Ihrer Anwendung entsprechend. Die Bibliothek sollte auch eine Plugin-Schnittstelle mit vielleicht nur einer "initialize" -Methode enthalten, die das Plugin-Objekt implementieren wird.

Die Anwendung und das Plugin verlinkt offensichtlich gegen diese DLL und sobald das Plugin von der Anwendung geladen wird, sollte die Anwendung die Initialisierungsmethode des Plugins aufrufen, die Parameter haben wird, um alle Objekte zu akzeptieren, die zur Steuerung der Anwendung benötigt werden.

Eine gängige Methode, dies zu vereinfachen, besteht darin, eine Hierarchie ähnlich dem DOM in Ihrer Anwendung zu implementieren, damit das Plugin von einem Stammobjekt aus alle relevanten Objekte in Ihrer Anwendung erreichen kann.

+0

Hier ist ein guter Artikel, der im Detail erklärt, wie Plugins auf diese Weise zu erreichen sind: http://www.nuclex.org/articles/building-a-better-plugin-architecture#comment-738 – joshperry

0

Erstellen Sie ein Registrierungsobjekt, das an das Plugin in der Initialisierungsfunktion übergeben wird, die ein Wörterbuch der exponierten Komponenten enthält. Erlauben Sie dem Plug-in dann, einen Zeiger auf Komponenten nach Zeichenfolge-Name oder anderem Bezeichner aus dieser Registrierung anzufordern. Für eine stabile Schnittstelle wird die Art der Kompilierungssicherheit eingeschränkt.

Es gibt auch schwergewichtige Lösungen wie CORBA ...

+0

Das ist meist * identisch * zu meinem "so weit das Beste, was ich habe ..." Satz. Der einzige wirkliche Unterschied ist, ob sie nach Strukturelement oder nach einer String-Übergabe anfordern. Ich werde die Struktur wegen Typ Sicherheit über nehmen. –

+0

Ich kann mir keine andere Lösung für das Problem vorstellen. Was hast du über Evan gedacht? –

+0

Leider habe ich bisher nichts gefunden, was wirklich überlegen ist. Linux-rdynamic wäre wirklich schön gewesen. Ich habe begonnen, meine Plugin-API in eine Struktur zu konvertieren, und es ist * wirklich * zeitaufwändig, um richtig zu machen. –

0

Sie haben getan, dass in einem relativ guten Weg. Helper-Klassen sind oft der pure Weg, um (nur) neue Funktionen einzufügen. Wenn Sie Ihre Software neu gestalten, müssen Sie erwähnen, dass nicht jedes Plugin Zugriff auf Ihre Verwaltungsstruktur haben sollte. Es sollte also Unterschiede im Plugin-Design geben.

Eine Möglichkeit: Erstellen Sie einige abstrakte Klassen, die Sie erben, die mit der Funktionalität zum Festlegen der erforderlichen Zeiger auf Widgets oder so kommen.

Andere Möglichkeit: Haupt erweitern (Eltern) Klassen mit Funktionen von getParent() getMainWidget(), getParent() getConfigWidget() ....


Wenn es nur um dynamisch ist.. Laden UIs von Ihrer UI-Plugin ohne Zeiger zu verwenden, können Sie es wie auf dieser Seite beschrieben tun: http://dolzhenko.blogspot.com/2008/10/qt4-dynamic-loading-ui-from-other-ui_07.html

es ist mit ui-Files getan Sie über Ihre Haupt-config-Dateien oder was auch immer zugreifen können.

Verwandte Themen