Moin,
Das Problem das hier behoben werden soll ist folgendes: AutoIt räumt auf.
Aufräumen ansich ist nicht verkehrt und bewahrt vor unnötiger Schreibarbeit.
Das Array im Array dürfte jedem ein Begriff sein.
Leider funktionniert Struct im Struct bei AutoIt nicht, warum ?
Ganz einfach: Verliert AutoIt die direkte zuweisung der Struct über eine Variable wird die Struct gelöscht.
Da hilft es auch nicht, wenn man den Pointer sowie die Struktur hinterlegt hat.
Abhilfe soll dieses Skript schaffen. (Es befindet sich nicht in der "fertigen" Fassung, sondern in einer Debugversion mit eingebautem Test)
Sofern das Skript funktioniert kann ich es auch ins UDF Schema verfrachten, sodass es bequem eingesetzt werden kann.
"Funktionen und Sonstiges"
_SaveStruct($vStruct)
;Schützt eine DllStruct durch Zwischenlagerung vor dem bösen AutoIt Aufräumkommando.
_DeleteStruct($iPointer)
;Löscht gezielt eine DllStruct aus dem Lager.
$__Save_Intervall
;Zeigt an wie klein- oder großschrittig das Speicherarray erweitert oder verkürzt werden soll.
;bei sehr wenigen Structs ist kleinschrittiges vorgehen sinnvoll (z.B. 5)
;Bei sehr vielen Structs müsste somit sehr oft erweitert werden. Bei einem grßen Intervall (z.B. 50) braucht man hier aber nur eine Hand voll.
;Das Intervall darf beliebig im Skript an die Bedürfnisse angepasst werden.
Ich bitte darum das Skript anzutesten und auf Fehler zu untersuchen.
Wenn alles läuft wird es umgemodelt.
Durch Auskommentieren von Zeile 91 sieht man was passiert, wenn eine Struct verloren geht, aber der Pointer noch vorhanden ist.
"Hier steckt ein Skript"
#include <Array.au3>
Global $__Save_Array[1], $__Save_Anzahl = 0, $__Save_Intervall = 5
[/autoit] [autoit][/autoit] [autoit]Global $vTest, $aPTR[16], $iTmp
[/autoit] [autoit][/autoit] [autoit]For $i = 0 To 15 Step 1 ; 16 Structpointer ergammeln und versuchen die Daten zu lesen.
$aPTR[$i] = _ptr()
$vTest = DllStructCreate('int[2]',$aPTR[$i])
ConsoleWrite('Structinhalt: ' & DllStructGetData($vTest, 1, 1) & @CRLF)
Next
For $i = 0 To 15 Step 1 ; Alle 16 Structs wieder löschen.
$iTmp = Random(0, UBound($aPTR)-1,1)
_DeleteStruct($aPTR[$iTmp])
_ArrayDelete($aPTR, $iTmp)
Next
Func _SaveStruct($vStruct) ; Sichert eine Struct im Array.
$__Save_Anzahl += 1
Local $iUbound = UBound($__Save_Array)
[/autoit] [autoit][/autoit] [autoit]If $iUbound < $__Save_Anzahl Then
ReDim $__Save_Array[$iUbound + $__Save_Intervall]
ConsoleWrite('Array wurde vergrößert: ' & $iUbound + $__Save_Intervall & @CRLF)
EndIf
_Display($__Save_Array, 'Speichern', $__Save_Anzahl - 2)
[/autoit] [autoit][/autoit] [autoit]$__Save_Array[$__Save_Anzahl-1] = $vStruct
[/autoit] [autoit][/autoit] [autoit]EndFunc
[/autoit] [autoit][/autoit] [autoit]Func _DeleteStruct($iPointer) ; Löscht eine Struct mittels Pointer
[/autoit] [autoit][/autoit] [autoit]ConsoleWrite('Löschen: ' & $iPointer & @CRLF)
[/autoit] [autoit][/autoit] [autoit]For $i = 0 To UBound($__Save_Array) - 1 Step 1
If $iPointer = DllStructGetPtr($__Save_Array[$i]) Then
$__Save_Array[$i] = 0 ; Struct löschen
__Ordnen($i)
Return 1 ; 1 = Alles OK
EndIf
Next
ConsoleWrite('! ERROR: Struct an der Stelle: ' & $iPointer & ' nicht gefunden...' & @CRLF)
[/autoit] [autoit][/autoit] [autoit]EndFunc
[/autoit] [autoit][/autoit] [autoit]Func __Ordnen($iLeer) ; Sortiert etwas. Wird noch in die Löschen Funktion integriert.
[/autoit] [autoit][/autoit] [autoit]ConsoleWrite('Löschen: ' & $iLeer & @CRLF)
ConsoleWrite('Letztes: ' & $__Save_Anzahl - 1 & @CRLF)
; Alle Arrayelemente so an, dass keine Lücken enstehen.
; Da nur ein Element Leer sein kann (Aufruf nur durch Delete)
; wird einfach das Letzte belegte Element dahin verschoben.
_Display($__Save_Array, 'vorher', $__Save_Anzahl - 1)
[/autoit] [autoit][/autoit] [autoit]$__Save_Anzahl -= 1 ; Es gibt eine Struct weniger jetzt.
$__Save_Array[$iLeer] = $__Save_Array[$__Save_Anzahl] ; Austausch.
$__Save_Array[$__Save_Anzahl] = 0 ; Alte Struct löschen.
If ($__Save_Anzahl + $__Save_Intervall) < UBound($__Save_Array) Then
ReDim $__Save_Array[$__Save_Anzahl+1]
ConsoleWrite('Array wurde verkleinert: ' & $__Save_Anzahl+1 & @CRLF)
EndIf
_Display($__Save_Array, 'nachher', $iLeer)
[/autoit] [autoit][/autoit] [autoit]EndFunc
[/autoit] [autoit][/autoit] [autoit]Func _Display($a, $p = 'vorher', $iTmp = -1) ; Gibt eine Liste der Pointer der Structs im Array aus.
Local $s = '|---------- ' & $p & @CRLF, $u = UBound($a)
For $i = 0 To $u - 1 Step 1
If $i = $iTmp Then $s &= '> '
$s &= $i & ' ' & DllStructGetPtr($a[$i]) & @CRLF
Next
$s &= '|----------' & @CRLF & @CRLF
ConsoleWrite($s)
EndFunc
Func _ptr() ; erstellt eine Struct und gibt anschließend nur den Pointer raus.
[/autoit] [autoit][/autoit] [autoit]Local $vStruct = DllStructCreate('int[2]'), $iPointer
DllStructSetData($vStruct, 1, 1000, 1)
$iPointer = DllStructGetPtr($vStruct)
_SaveStruct($vStruct)
Return $iPointer
[/autoit] [autoit][/autoit] [autoit]EndFunc
[/autoit]Edit:
Habe das Skript jetzt etwas in Form gebracht und das Beispiel etwas umgebaut, damit es als "richtiges" Beispiel nutzbar ist.
Dateien im Anhang (da es 2 sind. Und so viele Spoiler machen keinen Spaß)
Optimal wäre eine freundliche Person mit guten Englischkenntnissen die Lust hat alles mal durchzulesen