Seite 1 von 1

PB DLL als Modul im Hauptcode

Verfasst: 30.04.2011 16:01
von smateja
Hallo zusammen,

ich versuche derzeit eine kleine eigene Sidebar in einem größeren Projekt zu realisieren.
Meine Idee war es diverse Sidebar Gadgets als DLL in mein Projekt einzubinden. Prinzipiell ist dies auch kein Problem.

Allerdings wenn ich auf Variablen aus meinem - nennen wir es mal "Regiezentrum" zurückgreifen möchte ecke ich an.
Ist dies überhaupt so realisierbar, dass aus einer DLL auf Globale Variablen des Hauptprogramms zurückgreifen kann?

Zudem die Frage - bzw. kann es sein, dass man auf Enumerationen eben sowenig zurückgreifen kann?

LG derweil

Re: PB DLL als Modul im Hauptcode

Verfasst: 30.04.2011 16:41
von ts-soft
Die DLL kennt die globalen Variablen des Programmes nicht, und umgekehrt kennt das Programm die globalen Variablen der DLL nicht.

Enumerationen sind konstanten und sind der DLL auch nicht von Hause aus bekannt.

Re: PB DLL als Modul im Hauptcode

Verfasst: 30.04.2011 16:53
von PMV
Eine DLL ist nichts weiter als eine selbständiges "Programm", das lediglich
seine Funktionalität anderen Programmen zur Verfügung stellt. Weder
das aufrufende Programm, noch die DLL haben irgend welche Kenntnis
über den jeweils anderen. Programme können lediglich auslesen, welche
Prozeduren eine DLL zur Verfügung stellt und darauf zugreifen.

MFG PMV

Re: PB DLL als Modul im Hauptcode

Verfasst: 30.04.2011 17:04
von TomS
smateja hat geschrieben:Zudem die Frage - bzw. kann es sein, dass man auf Enumerationen eben sowenig zurückgreifen kann?
Dafür eignen sich Includes hervorragend ;)
Dann haste zumindest mal alle Konstanten verfügbar ohne alles doppelt machen zu müssen.

Variablen musst du halt im Prozedurparameter übergeben oder du suchst mal nach Shared Memory hier im Forum.

Re: PB DLL als Modul im Hauptcode

Verfasst: 30.04.2011 17:43
von smateja
Merci erstmal für die Infos - das mit den includes für Enumerationen etc - ist schon mal ein sehr guter Anfang.

Habt ihr evtl. Ideen dennoch einen Datenaustausch zwischen DLL und Hauptprogramm zu realisieren.
Oder auch ganz anders gedacht - wie realisiert man Plugins für ein Programm?

LG

Re: PB DLL als Modul im Hauptcode

Verfasst: 30.04.2011 18:12
von TomS
Also ich würde das wie folgt versuchen.
Erst mal überlegen, was ein Plugin alles können muss.
zB. Einen Menüeintrag (oder ein ganzes Submenu) in der Menubar unter "Plugins" erstellen. (Datei, Bearbeiten, Ansicht, Plugins, Hilfe...).
Oder einen Button in der Toolbar erstellen.

Dann legt man fest, wie die Funktionen heißen müssen. Z.B. MyProg_Plugin_Init(param...), MyProg_Plugin_Main(param....)
Diese Funktionen werden vom Hauptprogramm mit entsprechenden Parametern aufgerufen (ein wichter Parameter wäre z.B. hWnd, also WindowID(#Window_0), oder auch EventGadget(), EventType() etc, je nach Programmtyp).

Zum Datenaustausch wie gesagt SharedMemory, wenn die DLL eher ein eigenständiges Programm ist.
Für einfache Rückgabewerte kann man einfach ProcedureReturn benutzen.



Hier mal mein angefangens Mini-Pluginsystem (ohne Shared Memory)

Code: Alles auswählen

;Main.pb
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 

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 
Das ist natürlich ein dämliches Plugin, dass nicht's kann. Außerdem ist die absolute Position des Buttons mehr als ungünstig. X und Y Position sollte evtl vom Hauptprogramm an die DLL übergeben werden...
Aber ist ja nur ein kleines Beispiel ;)

Re: PB DLL als Modul im Hauptcode

Verfasst: 02.05.2011 18:22
von Thorium
Eine DLL ist kein eigenständiges Programm, sie läuft im Context des aufrufenden Prozesses und hat in diesem Sinne Kenntnis vom Programm. Und natürlich kann man auch auf Variablen des Hauptprogramms zugreifen ohne Shared Memory. Die DLL läuft sowieso im gleichen Prozessspeicher. Allerdings kann man das nicht direkt, da der Compiler den Namen keine Adressen zuordnen kann. Der gängige Weg ist es eine initialisierungsprozedur in der DLL zu haben, welche einen Pointer auf eine Datenstruktur erwartet, welche eben die globalen Variablen enthält. Kann auch Pointer auf Prozeduren vom Hauptprogramm enthalten, welche die DLL dann ausführen kann.

Hier habe ich so ein Plugin System mit DLL's realisiert: http://www.purebasic.fr/german/viewtopi ... 0&p=233466

Ist extrem simpel aufgebaut, du wirst es etwas komplexer benötigen aber da siehst du wie du auf Variablen und Prozeduren zugreifen kannst.

Re: PB DLL als Modul im Hauptcode

Verfasst: 02.05.2011 19:31
von PMV
Ja und Nein. Prozess und DLL können zwar auf den jeweils anderen zugreifen,
haben aber in erster Linie keine Kenntnis davon. Deswegen das "eigenständige
Programm". Erst wenn man über Prozeduren einen Datenaustausch macht, dass
heißt die Zeiger überträgt, haben beide Kentniss davon. Aber das heißt noch
lange nicht, dass man im jeweils anderen Speicherbereich munter rumschreiben
und ihn verändern darf. Erst reicht wenn man die eigenen internen Verwaltungen
von PB bedengt. Lesen ist allerdings in keinem Fall ein Problem. Natürlich so
lange der Speicherbereich auch gültig ist. Der Prozess kann logischer weise nicht
in Speicher der DLL lesen, wenn die DLL diesen bereits freigegeben hat.

Es ist aber zu lange her, als das ich näher ins Detail gehen will und am Ende doch
was falsches sag, deswegen hab ich mich bisher so kurz gehalten :)
Sicher bin ich mir nur noch darinn, dass ich einige Stolperfallen umschiffen musste.
:lol:

Ach ja ... damit sollte man sich auch nur beschäftigen, wenn man sicher mit
Zeigern umgehen kann. :wink:

MFG PMV

Re: PB DLL als Modul im Hauptcode

Verfasst: 02.05.2011 20:05
von 125
Moin,
in aller Kürze:
Der Vorteil einer DLL besteht darin, das man sie in mehreren Programmen nutzen kann und nur einmal Speicher verbraucht, da man nicht statisch ins Programm linkt. Falls du das ganze nur in diesem einen Programm benötigst, nehme einen Include und linke lieber statisch.

Gerade bei solchen Dingen wie einer DLL (allerdings auch generell bei Includes etc) sollte man ein sehr genaues Interface deklarieren, sodass die DLL und der Hauptprogrammcode über eine vereinheitlichte Schnittstelle kommunzieren können. Hierfür bieten sich Datenstrukturen und Konstanten als Rückgabewert und Parameter an. Denn was bringt letztendlich eine DLL wenn sie den Programmcode der sie aufruft kennen muss. Das wiederspricht sich. Lese dir falls möglich mal was zum Konzept der Modularisierung und was zum Schichtenmodell durch.

Auf globale Variablen sollte man so wie es irgendwie machen lässt verzichten. (Zumindest Includeübergreifend, denn nur durch Kapselung lässt sich optimale austauschbarkeit und reusability garantieren)

Hoffe das hilft dir weiter. Hätte noch mehr geschrieben aber ich habe leider gerade wenig Zeit. ;)

MfG
125

Re: PB DLL als Modul im Hauptcode

Verfasst: 07.05.2011 13:40
von tft
Hallo,

Ich bin mir da nicht sicher,aber in der Version 1.01 von PB gab es mal die Möglichkeit mit der VarImport / Export Directive der Dll Variablen Namen bekannt zu geben. Das funktionierte aber nur mit PB. Andere Programme konnten diese speziellen Dll Dateien nicht verwenden da sie nicht dem Standard entsprach. Das war sehr nützlich. Es liessen sich Programmteile zur Laufzeit austauschen. Fileicht weis einer der Spezis hir ob das noch geht.

Gruß TFT