Seite 1 von 2

Beim Beenden, Funktionen automatisch aufrufen

Verfasst: 06.08.2007 01:35
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 : ")


Verfasst: 06.08.2007 09:43
von bobobo
und nun noch bitte irgendeine erklärung für was das gut sein soll.

Verfasst: 06.08.2007 15:50
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

Verfasst: 06.08.2007 21:40
von X0r
:allright: kann ich gebrauchen

Verfasst: 07.08.2007 13:58
von bobobo
ist dann eine möglichkeit für schlampige programmierer

naja

wer's anders nicht gebacken bekommt :mrgreen:

Verfasst: 07.08.2007 14:21
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:

Verfasst: 07.08.2007 15:03
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.

Verfasst: 07.08.2007 21:06
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 ?

Verfasst: 08.08.2007 20:51
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

Verfasst: 08.08.2007 20:58
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: