Seite 1 von 1

Plugin Interface- Wie am besten umsetzten?

Verfasst: 16.05.2014 01:28
von nicolaus
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

Re: Plugin Interface- Wie am besten umsetzten?

Verfasst: 16.05.2014 22:54
von TroaX
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. ;)

Re: Plugin Interface- Wie am besten umsetzten?

Verfasst: 16.05.2014 23:12
von Derren
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 :D


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.

Re: Plugin Interface- Wie am besten umsetzten?

Verfasst: 21.05.2014 11:21
von nicolaus
Ich danke euch schon mal.
Das Sample hilft super!