PB DLL als Modul im Hauptcode

Anfängerfragen zum Programmieren mit PureBasic.
smateja
Beiträge: 250
Registriert: 25.11.2004 19:51
Computerausstattung: Alienware Aurora / Intel Core i7 CPU @ 2.8 GHz / 64 Bit OS

PB DLL als Modul im Hauptcode

Beitrag 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
PB 4.6 / 32 Bit / 64 Bit
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: PB DLL als Modul im Hauptcode

Beitrag 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.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Re: PB DLL als Modul im Hauptcode

Beitrag 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
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
TomS
Beiträge: 1508
Registriert: 23.12.2005 12:41
Wohnort: München

Re: PB DLL als Modul im Hauptcode

Beitrag 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.
smateja
Beiträge: 250
Registriert: 25.11.2004 19:51
Computerausstattung: Alienware Aurora / Intel Core i7 CPU @ 2.8 GHz / 64 Bit OS

Re: PB DLL als Modul im Hauptcode

Beitrag 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
PB 4.6 / 32 Bit / 64 Bit
Benutzeravatar
TomS
Beiträge: 1508
Registriert: 23.12.2005 12:41
Wohnort: München

Re: PB DLL als Modul im Hauptcode

Beitrag 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 ;)
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Re: PB DLL als Modul im Hauptcode

Beitrag 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.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Re: PB DLL als Modul im Hauptcode

Beitrag 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
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
125
Beiträge: 1322
Registriert: 19.09.2004 16:52
Wohnort: Neu Wulmstorf (Hamburg)
Kontaktdaten:

Re: PB DLL als Modul im Hauptcode

Beitrag 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
Bild
BildDas ist Tux. Kopiere Tux in deine Signatur und hilf ihm so auf seinem Weg zur Weltherrschaft.
Benutzeravatar
tft
Beiträge: 650
Registriert: 08.09.2004 20:18
Computerausstattung: GFX 3060 Ti , i7 12700F , 32 GB Ram , 900 GB SSD , TV
Wohnort: Dachsen
Kontaktdaten:

Re: PB DLL als Modul im Hauptcode

Beitrag 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
TFT seid 1989 , Turgut Frank Temucin , CH-Dachsen/DE-Berlin/TR-Antalya
Mein Projekt (Driving School Evergarden)
Codes bei (GitHub) Videos von (YouTube)
Treffen via Discord: Einladung

PB 6.10 | W11 | i7 12700F | 32 GB Ram | RTX 3060 Ti | 60 Herz -TV FullHD
ARDUINO Freak | Sprecher | Game Dev. | Geschichten Erzähler :-)
Antworten