Hi zusammen,
mal ne frage, wie kann man am besten ein Plugin-Interface umsetzten um seinem Programm die Pluginmöglichkeit zu geben?
Ich überlege schon ein stück wie ichg das am besten realisieren könnte, habeaber noch nicht wirkllich den richtigen weg gefunden.
Was bedingung ist:
- Plugins müßen alls dll vorliegen
- Programm soll Plugins aus Folder XXX automatisch erkennen
Danke euch schon mal für eventzuelle Anregungen.
Nico
Plugin Interface- Wie am besten umsetzten?
- TroaX
- Beiträge: 720
- Registriert: 08.03.2013 14:27
- Computerausstattung: PC: Ryzen 9 3950X, 96 GB RAM, RX6800XT, 2.5 TB SSD, 21:9 Display, Linux Mint | Lappi: Ryzen 7 5800H, 16 GB RAM, 1 TB SSD, Linux Mint
- Wohnort: NRW
- Kontaktdaten:
Re: Plugin Interface- Wie am besten umsetzten?
Im Grunde ist das ja garnet so schwer. Du definierst einen Ordner, in dem die Plugins sind. Bei Programmstart durchsuchst du diesen Ordner nach DLL's, öffnest die mit OpenLibrary und führst eine festgelegte Prozedur aus der DLL aus. Das ist grob der einfachste Ansatz. 
PC: Ryzen 9 3950X | 96 GB RAM | RX6800XT | 2,5 TB NVMe | Linux Mint
Notebook: 16" 3:2 | Ryzen 7 5800H | 16 GB RAM | Radeon Vega | 1TB NVMe | Linux Mint
NAS: N150 Mini-PC | 16 GB RAM | Debian 13+CasaOS
Coding: Purebasic, Spiderbasic, Gambas
Blog: https://techtroax.de
Repos: https://codeberg.org/TroaX
Notebook: 16" 3:2 | Ryzen 7 5800H | 16 GB RAM | Radeon Vega | 1TB NVMe | Linux Mint
NAS: N150 Mini-PC | 16 GB RAM | Debian 13+CasaOS
Coding: Purebasic, Spiderbasic, Gambas
Blog: https://techtroax.de
Repos: https://codeberg.org/TroaX
Re: Plugin Interface- Wie am besten umsetzten?
Ich hab sowas mal angefangen, aber nachdem das Hauptprojekt derzeit auf Eis liegt, wurde das Pluginsystem auch nicht weiter entwickelt.
Hier, ist sogar kommentiert, dein Glück
Plugin Host
Testplugin, als DLL kompiliert und in den angegebenen Unterordner geschoben.
Der Host erlaubt den Plugins Gadgets zu erstellen. Das sollte viel restriktiver sein, damit sich keine Gadgets von verschiedenen Gadgets überlagern. Aber oftmals öffnet sich für ein Plugin eh ein neues Fenster. Dann gibt es keine Probleme.
Wenn ein Gadget betätigt wird, wird die plugin_eventgadget() Funktion aufgerufen. Somit kann das Gadget reagieren. Das ist nicht sehr elegant, dafür einfach.
Man kann natürlich auch jedes vom Plugin erstelle Gadget an den Host senden, so dass dieser erstmal prüft zu welchem Plugin der Button gehört, bevor die entsprechende Pluginfunktion aufgerufen wird.
Man kann immer alles besser machen und sich natürlich fragen ob man ein System entwickeln will, dass sich auf Riesenanwendungen á la Photoshop hochskalieren lässt, oder ob man eher erstmal kleinere Brötchen backt.
Hier, ist sogar kommentiert, dein Glück
Plugin Host
Code: Alles auswählen
EnableExplicit
Define PS_PluginPath .s = "plugins/" ;Pfad und ID des Plugin Ordners.
Define PS_PluginDirectoryID .i
Define.i WindowEvent, EventGadget, Main_WindowID
Prototype proto_init(hWnd.i) ;Prototypen der Plugin-Funktionen
Prototype proto_eventgadget(eventgadget.i)
Structure plugins_structure ;Struktur, welche die LibraryID enthält
libID .i ;und alle Prototype-Funktionen
plugin_init .proto_init
plugin_eventgadget .proto_eventgadget
EndStructure
NewList plugins.plugins_structure() ;Liste aller Plugins
Define PS_PluginDirectoryID = ExamineDirectory(#PB_Any, PS_PluginPath, "*.dll") ;Pluginordner durchkämmen und jede DLL laden
While NextDirectoryEntry(PS_PluginDirectoryID)
AddElement(plugins())
With plugins()
\libID = OpenLibrary(#PB_Any, PS_PluginPath + DirectoryEntryName(PS_PluginDirectoryID)) ;DLLs laden und Funktionen mit
\plugin_eventgadget = GetFunction(\libID, "plugin_eventgadget") ;Prototype in die Struktur speichern
\plugin_init = GetFunction(\libID, "plugin_init")
EndWith
Wend
Main_WindowID = OpenWindow(#PB_Any , 0, 0, 400, 300, "plugin test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ForEach plugins()
plugins()\plugin_init(WindowID(Main_WindowID)) ;Init-Funktion aller Plugins aufrufen.
Next
Repeat
WindowEvent = WaitWindowEvent(20)
Select WindowEvent
Case #PB_Event_Gadget
EventGadget = EventGadget()
Select EventGadget
Case -900 ;Irgendeinen Unsinn, damit "Default" funktioniert
Debug "..."
Default
ForEach plugins() ;EventGadget an alle Plugins weiterleiten, die selbst überprüfen,
plugins()\plugin_eventgadget(EventGadget) ;ob das EventGadget zum Plugin gehört
Next
EndSelect
EndSelect
Until WindowEvent = #PB_Event_CloseWindow
End Testplugin, als DLL kompiliert und in den angegebenen Unterordner geschoben.
Code: Alles auswählen
;test.dll
Define button.i
ProcedureDLL plugin_init(hWnd.i)
Shared button
UseGadgetList(hWnd) ;Vom Hauptprogramm mitgeteilte GadgetList verwenden (Fenster oder auch ContainerGadget etc...)
button = ButtonGadget(#PB_Any, 0, 0, 100, 20, "Plugin")
EndProcedure
ProcedureDLL plugin_eventgadget(eventgadget.i)
Shared button
If eventgadget = button ;Das Plugin überprüft selbst, ob das EventGadget ein eigenes ist und führt entsprechend Code aus.
MessageRequester("Plugin","Button pushed")
EndIf
EndProcedure Der Host erlaubt den Plugins Gadgets zu erstellen. Das sollte viel restriktiver sein, damit sich keine Gadgets von verschiedenen Gadgets überlagern. Aber oftmals öffnet sich für ein Plugin eh ein neues Fenster. Dann gibt es keine Probleme.
Wenn ein Gadget betätigt wird, wird die plugin_eventgadget() Funktion aufgerufen. Somit kann das Gadget reagieren. Das ist nicht sehr elegant, dafür einfach.
Man kann natürlich auch jedes vom Plugin erstelle Gadget an den Host senden, so dass dieser erstmal prüft zu welchem Plugin der Button gehört, bevor die entsprechende Pluginfunktion aufgerufen wird.
Man kann immer alles besser machen und sich natürlich fragen ob man ein System entwickeln will, dass sich auf Riesenanwendungen á la Photoshop hochskalieren lässt, oder ob man eher erstmal kleinere Brötchen backt.
Signatur und so
Re: Plugin Interface- Wie am besten umsetzten?
Ich danke euch schon mal.
Das Sample hilft super!
Das Sample hilft super!