Beim Beenden, Funktionen automatisch aufrufen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beim Beenden, Funktionen automatisch aufrufen

Beitrag von edel »

Unter FreeBasic gibt es Modul-Destruktoren, unter PB, wer haette das
gedacht :D, nicht. Mit dem folgendem Code kann man das aber etwas
ausbuegeln.

Mit der Funktion "Destructor", oder wie immer man es auch nennen mag,
werden die einzelnen Funktionen in einer Liste gespeichert, und beim
beenden des Programmes automatisch aufgerufen. Die ersten Funktionen
werden immer zuletzt aufgerufen, es sei denn man gibt eine
entsprechende Prioritaet mit an, je hoeher diese ist, desto frueher wird
die Funktion aufgerufen. Nebem der Prioritaet kann man noch irgendeinen
Wert mit uebergeben, der dann spaeter an die Funktion weitergeleitet wird.

In diesem Beispiel sieht der Prototyp der Destruktoren so aus :

Code: Alles auswählen

Prototype CallExitProc(param)

Code: Alles auswählen

Prototype CallExitProc(param)

Structure pbcallfunc
   call.CallExitProc
   prio.l
   param.l
EndStructure

Global NewList CALLFUNCOBJ.pbcallfunc()

oldExitProtect    = 0
*ExitOffset.long  = 0

!MOV eax,_PB_EOP
!ADD eax,1
!MOV [p_ExitOffset],eax

Procedure cf_Destructor()
   ForEach CALLFUNCOBJ()
      CALLFUNCOBJ()\call(CALLFUNCOBJ()\param)
   Next
   !CALL _PB_EndFunctions
EndProcedure

Procedure Destructor(proc,prio=#PB_Ignore,param=0)
   Static wprio.l = #PB_Ignore
   
   If proc
      If InsertElement(CALLFUNCOBJ())
         
         CALLFUNCOBJ()\call  = proc           
         CALLFUNCOBJ()\param = param
         
         If prio = #PB_Ignore
            CALLFUNCOBJ()\prio = wprio 
            wprio + 1
         else
            CALLFUNCOBJ()\prio  = prio 
         EndIf  
         
         SortStructuredList(CALLFUNCOBJ(),1,OffsetOf(pbcallfunc\prio),#PB_Sort_Long) 
      EndIf 
   EndIf
EndProcedure

VirtualProtect_(*ExitOffset,4,#PAGE_READWRITE,@oldExitProtect)
*ExitOffset\l = @cf_Destructor() - (*ExitOffset + 4)
VirtualProtect_(*ExitOffset,4,oldExitProtect,@oldExitProtect)
Beispiel :

Als Consolen-Programm kompilieren !

Code: Alles auswählen

Procedure exit1(param)
   PrintN("ende : 1 -> " +Str(param))
EndProcedure

Procedure exit2(param)
   PrintN("ende : 2 -> " +Str(param))
EndProcedure

Procedure exit3(param)
   PrintN("ende : 3 -> " +Str(param))
EndProcedure

Procedure exit4(param)
   PrintN("ende : 4 -> " +Str(param))
EndProcedure

Destructor(@exit1())
Destructor(@exit2(),10)
Destructor(@exit3(),1,444)
Destructor(@exit4(),1)

OpenConsole()
PrintN("Ausgabe : ")

Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

und nun noch bitte irgendeine erklärung für was das gut sein soll.
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Beim Beenden, Funktionen automatisch aufrufen
:mrgreen:

Ich habe in meinem Programm eine Menge an Abbruch-Bedingungen,
um nun nicht jedes mal die Aufraeumarbeiten dazuzuschreiben,
wird eben am Ende alles aufgeraeumt.
Fuer was man solche Funktionen am Ende nutzt, bleibt aber jedem
selber ueberlassen.

Dieses Beispiel (Macht unter PB4 so keinen Sinn mehr) stuertzt beim
beenden ab, da das Scintilla Fenster auf Funktionen zugreifen moechte
die PB schon freigebeben hat.

Code: Alles auswählen

OpenLibrary(-1,"scintilla")

hWnd = OpenWindow(0,#PB_Ignore,#PB_Ignore,640,480,"leer",#WS_OVERLAPPEDWINDOW)


CreateGadgetList(hWnd)
ScintillaGadget(0,0,0,640,480,0)

Repeat
	event = WaitWindowEvent()

Until event = #PB_Event_CloseWindow
Dieses Beispiel beenden sich dagegen richtig :

Code: Alles auswählen

Procedure FreeSCI(id)
	FreeGadget(id)
EndProcedure

OpenLibrary(-1,"scintilla")

hWnd = OpenWindow(0,#PB_Ignore,#PB_Ignore,640,480,"leer",#WS_OVERLAPPEDWINDOW)


CreateGadgetList(hWnd)
sci = ScintillaGadget(-1,0,0,640,480,0)

Destructor(@FreeSCI(),#PB_Ignore,sci)

Repeat
	event = WaitWindowEvent()

Until event = #PB_Event_CloseWindow
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Beitrag von X0r »

:allright: kann ich gebrauchen
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

ist dann eine möglichkeit für schlampige programmierer

naja

wer's anders nicht gebacken bekommt :mrgreen:
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
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

Beitrag von ts-soft »

bobobo hat geschrieben:ist dann eine möglichkeit für schlampige programmierer

naja

wer's anders nicht gebacken bekommt :mrgreen:
Bei OCX oder Controls aus DLLs allgemein, gibts am Programmende einen
IMA, weil PB in einer ungünstigen Reihenfolge aufräumt. Dieser Fehler wird
dadurch behoben, indem man selber autom. das Object freigibt, bevor PB die
DLL entlädt. Normallerweise bräuchte man es nicht, PB gibts ja frei, aber die
Reihenfolge haut nicht hin. Wenn PB erst Controls und Fenster freigeben
würde, bevor DLLs entladen werden wäre der Code von edel unnütz, so finde
ich ihn recht praktisch.

Besser wäre aber, wenn PB in einer IMHO sinnvolleren Reihenfolge die
Objecte freigeben würde. bei den PureDisphelper Beispielen muß vor
Programmende jedesmal das Fenster geschlossen werden, damit es nicht
Kracht, wenn PB das Object/OCX entlädt.

Aber bevor ich diesen für mich nicht so verständlichen Code verwende,
schliesse ich lieber am Ende das Fenster :mrgreen:
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
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

ts-soft hat geschrieben:
bobobo hat geschrieben:ist dann eine möglichkeit für schlampige programmierer

naja

wer's anders nicht gebacken bekommt :mrgreen:
Bei OCX oder Controls aus DLLs ..
na genau das schrob ich doch ..wer es anders nicht gebacken bekommt.
also für alle apihengste die pb zur fernsteuerung von windoof
verwenden.
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

bobobo hat geschrieben:ist dann eine möglichkeit für schlampige programmierer

naja

wer's anders nicht gebacken bekommt :mrgreen:
:roll:

Schreibst du deine Programme auch in Maschinensprache
oder bekommste das etwa auch nicht 'gebacken' ?

Das obige Beispiel ist ein ganz normaler Vorgang, oder
wolltest du, unter PB, jede einzelne ObjectListe per Hand
freigeben ?
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

es geht um pb, oder?

und da ist das apigedöns eben nativ nicht mit drin

dein destruktor ist natürlich brauchbar (wenn man es mit pb
nicht gebacken bekommt) :)

ich bin ja schon still
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
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

Beitrag von ts-soft »

bobobo hat geschrieben: und da ist das apigedöns eben nativ nicht mit drinl
Der Code enthält fast garkeine API, sondern nutzt PB :mrgreen:
Nur eben interne Funktionen, wie den PB Objectmanager usw.
VirtualProtect_ ist die einzige API die vorkommt, wenn ich nichts übersehen habe :wink:
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
Antworten