Guten Tag,
Diese UDF ermöglicht das (relativ) einfache Erzeugen von COM-Objekten in AutoIt. Dabei wird die Syntax von Sprachen die OOP nativ unterstützen teilweise imitiert (wozu das Rad neu erfinden), sodass man sowohl als Einsteiger als auch als alter Hase schnell zurechtfindet.
Wie funktioniert das ganze?
Das ist eine gute Frage , es gibt die wunderbare BuiltIn Funktion ObjCreateInterface die so umständlich zu handhaben ist, dass niemand viel damit angefangen hat und niemals ans Licht kam was man damit alles anstellen kann. Die hier erzeugbaren Objekte bestehen aus einer DllStruct die Objektvariablen und Callbacks zu AutoIt-Funktionen beinhaltet. Da es sehr viel Aufwand ist diese Struct jedes Mal manuell zu erstellen nimmt einem die UDF diesen Part der Arbeit ab. Die AutoIt-Funktionen die später als Objekt-Methoden dienen muss man natürlich trotzdem von Hand schreiben.
Was geht:
- Objektvariablen MIT Datentyp (kein Variant, genauso wie die Datentypen in DllStructs)
- Methoden mit Alias, man kann also eine Funktion schreiben die zwar __IchBin_EinKomplizierterName_BerechnePI() heißt, vom Objekt aber als $o.PI aufgerufen werden kann (bei Methoden gilt etwas das für AutoIt-Funktionen nicht gilt, haben sie keinen Parameter kann man die Klammern weglassen)
- Objekte in Objekten (was wäre die Welt, wenn man ein Rechteck aus 4 Zahlen und nicht aus 2 Punkten definieren müsste)
- Zugriff auf Objektvariablen und Methoden von außerhalb und innerhalb von Objekten (jetzt auch ohne Maps, keine BETA Pflicht mehr)
- Vieles mehr (was man eben so alles anstellen kann)
Bekannte Bugs/Probleme/ToDo-Liste (je nachdem wie man es nennen will):
- Objektvariablen sind alle "privat", man kann nicht via $o.x auf die Variable x aus $o zugreifen. Man kann aber die Struct die die Variablen enthält auch von außerhalb erreichen und so die Objektvariablen lesen und schreiben... Das ganze lässt sich wrappen, aber (zumindest nach meinem Kenntnissstand) nicht trivial als $o.x.
- ByRef funktioniert in Objektmethoden nicht. (DllCallbackRegister will sowas nicht... ob man das wrappen kann muss noch erörtert werden, sieht aber schwierig aus)
- Arrays können nicht an Methoden übergeben werden. (DllCallbackRegister will sowas nicht... ob man das... siehe oben)
Edit: 18.Mär.19
Rebrand:
- Die UDF heißt jetzt NAUO (Native AutoItObject) um Namenskollisionen mit der AutoItObject UDF von ProgAndy zu verhindern. (Native weil keine DLLs oder andere Zusatzsoftware benötigt wird)
Added:
- Method(string, [string, [string, [string, [string]]]]) kann jetzt die Parameter auch im ersten String haben, z.B. Method('Math_Sqrt[Sqrt](double, double)') = Method('Math_Sqrt[Sqrt]', 'double', 'double')
- Var(Obj, string) -> Read Variable called "string"
- Var(Obj, string, x) -> Write x into Variable called "string"
BugFixes:
- Objekte ohne Variablen führen nun nicht mehr zum Absturz.
Script Breaking Changes:
- New('String', $this) liefert jetzt automatisch New('String', $this).Ptr, in alten Skripten muss also das .Ptr entfernt werden (verschachtelung von Objekten, Siehe Beispielskript 2).
Ladet den Anhang herunter und probiert die 4 Beispiele mal aus
Anregungen oder Wünsche oder Bugmeldungen sind gerne gesehen, nur so kann die UDF weiterentwickelt werden. Ich bin aber ein fauler Mensch und es kann Monate oder Jahre dauern bis ich an der UDF weiterarbeite
Alter inhalt
Seit AutoIt die Funktion ObjCreateInterface besitzt ist es möglich mit kleinem Aufwand "echte" Objekte zu erzeugen. In den letzten Tagen ist daraus eine kleine UDF entstanden. Sie befindet sich im Aufbau und bietet aktuell deutlich weniger als Konkurrenzprodukte welche auf externe Dateien wie DLLs, oder nicht Standard UDFs zurückgreifen. Sie soll auch keine echte Konkurrenz darstellen, sondern eine einfache und kleine Lösung bieten.
Für Interessierte:
Es steht jedem frei Features zu wünschen, Bugs zu melden oder Beispiele zu OOP und spezifischen Problemen zu verfassen (bitte im Thread hier posten). Dabei sollte darauf geachtet werden, dass die UDF möglichst unabhängig bleibt (also keine DLLs, keine nicht Standard UDFs und StandardUDFs nur im Notfall). Optimal wäre es natürlich, wenn man zu Problemen die man findet eine geeignete Lösung parat hat, falls dem nicht so ist kommt der Bug auf die Liste, gleiches gilt für Features.
Manche Funktionen der UDF setzen die BETA voraus, so werden Methoden in Methoden Beispielsweise als Map gehandelt (sodass man möglichst einfach an die Methoden kommt).
Wir freuen uns über jeden der etwas zu der UDF sagt, oder sie verbessern/benutzen möchte.
Update 05.01.2019:
In letzter Zeit kamen mir ein paar Ideen wie man die "umständliche" Verwendung der UDF ein wenig auslagern kann, sodass die Bedienung stark vereinfacht wird (man kann Objekte jetzt "ähnlich" (aber nicht gleich) wie in anderen Sprachen deklarieren. Außerdem sind ein paar kleine neue Features/Fixes hinzugekommen. Das Ganze ist noch nicht gut kommentiert und UDF-Header mit Erklärungen gibt es auch erst später, aber man kann schonmal reinschauen.
Hinweis: Die Klassen müssen immer VOR der Verwendung deklariert werden, da AutoIt keine Keywords "Class" oder "Method" besitzt werden diese durch Funktionen imitiert die ausgeführt werden müssen bevor es möglich ist Instanzen einer Klasse zu erzeugen. Klassen also am besten Themenbedingt in einzelne Dateien verpacken und diese zu Beginn includen, dann kann nichts schiefgehen.
Die UDF + Beispiel gibts im Anhang.
Offene Fragen:
- Wie speichert man Objekte in Objektvariablen? (Diese Variablen sind nur primitive Datentypen, kann man ggf. via oPtr Objekte verschachteln?)
- Kann es möglich sein Klassen innerhalb von Funktionen/Anderen Anweisungen zu deklarieren? (Aktuell MÜSSEN Klassen toplevel deklariert werden, da das Func-Keyword für Methoden benutzt wird was es leider ausschließt woanders ausgeführt zu werden....)
Wie immer gilt: Wer Vorschläge (Antworten) hat, her damit (auch wenn ich 3 Jahre brauche bis ich darauf zurück komme )
Gelöste Fragen:
# Objekte in Objekten # 06.01.2019
Erstmal wird ein Objekt automatisch gelöscht, sobald die letzte AutoIt-Interne Referenz verlorengeht. Also muss dafür gesorgt werden, dass Objekte die man nur via ptr speichern will dennoch erhalten bleiben. Zum Glück haben Objekte einen einzigartigen Ort im RAM (ptr) den man super als Hashkey benutzen kann, sodass jedes Objekt bei der Erzeugung in einem Hashtable hinterlegt wird. Möchte man nun via ptr darauf zugreifen muss man nur im HashTable wühlen und das Objekt wieder herausholen. Das geht von überall aus, sodass man Objekte in Objekten ohne Probleme als Variablentyp ptr speichern kann. Damit AutoIt korrekt löscht, wenn z.B. ein Objekt das Objekte enthält gelöscht wird muss der Destruktor benutzt werden, in diesem werden alle child Objekte abgearbeitet (aus dem Hashtable löschen). Dabei taucht ein neues Problem auf: Was ist, wenn ein Objekt in mehreren anderen Objekten enthalten ist? Dann wird es im Hashtable nur 1x hinterlegt und liefert eine ungültige Referenz sobald es gelöscht wird, obwohl es in anderen Objekten ggf. noch vorkommt. Abhilfe könnte hier ein Hash aus (ptr Child & ptr Parent) liefern, dann wird jedes Objekt so oft in den HT gelegt wie es referenziert wird. Da das ganze nicht so rund läuft wie ich es gerne hätte und vorallem noch NICHT automatisiert ist (man muss child Objekte explizit löschen, das lässt sich sicherlich wrappen, sodass man sich als Benutzer nicht darum kümmern muss) gibts noch kein Update der Dateien an dieser Stelle.
Update 06.01.2019:
Es ist nun möglich Objekte innerhalb von Objekten zu erzeugen. Die Ganze Sache ist noch etwas holprig (und nicht vollständig gewrappt) funktioniert aber schonmal. Daher gibt es ein Beispiel02 welches ein Rect durch 2xPoint definiert.
lg
M