Hi all
aus den Beschreibungen die Siemens so liefert, wird man zwar schlauer, aber nicht klug. Hier mal meine Zusammenfassung:
Variant ist nicht Any. Variant ist mehr! Und Pointer ist er auch nicht, denn der kann noch weniger.
Pointer zeigt auf ein einzelnes Bit irgendwo im Standard-Speicher einer Simatic. Warum er nicht auf optimierten Speicher zeigen kann ... ist "böse" Absicht :-|. Damit hat er in etwa den Nutzen eines Byte* aus C, du kannst das auf alles casten was du willst. Aber wehe du machst es falsch, dann viel Spaß beim Fehlersuchen. Noch schlimmer wenn es nicht dein eigener Code ist.
Any zeigt auf einen Bereich irgendwo im Standard-Speicher einer Simatic. Auch der kann nicht auf optimierten Speicher. Der Any kann was über den Datentyp des Speichers wissen, auf den er zeigt. Er kann die einfachen Datentypen unterscheiden. er kann z.B. auf ein Feld von 20 REAL zeigen. Er kann jedoch nicht auf einen String[47] oder einen UDT5 zeigen. Aus komplexen Datentypen werden (fast) immer Byte-Arrays.
Variant zeigt auf einen Bereich irgendwo im Speicher einer Simatic. Der kann auf optimierten Speicher zeigen. Der Variant weiß was über den Datentyp. Er kann sich (fast?) alle Datentypen merken. Also auch sowas wie array[20] of UDT21. Klingt doch gut!
... naja ... hier tritt der erste Mangel zutage. Er weiß nichts über die Ober und Untergrenzen von Arrays. Was nicht geht ist ein Array[1..5] of FB7. Also ein Feld aus Instanzen. Das ist jetzt ein Henne-Ei-Problem. Man kann das nicht Deklarieren, also kann der Variant auch nicht drauf zeigen. Oder ist das umgekehrt? Egal, Instanz-Arrays gehen nicht. :neutral:
Also ist der Variant deutlich besser als ein Any. Und gleichzeitig ist er für den AWL-Profi deutlich schlechter, denn es gibt keine Möglichkeiten den Variant zu manipulieren. Auch das ist Absicht, hat mit der CS versichert :evil:
Zur V12 konnte man mit den Variant nichts machen. Es gab Systemfunktionen, die damit zauberten, aber für uns normal sterbliche Anwender, war nur durch reichen. Seit der V13 kommt Bewegung in die Sache. Leider viel zu viel Bewegung. Es gibt jetzt zwei Funktionen VariantGet und VariantPut, die es uns erlauben zu dereferenzieren.
Wenn du einen Input vom Typ Variant und einen Temp von irgendeinem Typ, sagen wir mal UDT13, anlegst, dann kannst du mit VariantGet den Inhalt des UDT13 kopieren. Das finde ich ziemlich blöd, denn wenn der UDT13 nun so 1k groß ist, dann wird da ein ganzes Kilobyte kopiert :shock:. Wenn du einen InOut anlegst dann kannst du sogar mit dem VariantPut rein schreiben. Das setzt voraus, dass du beim Aufruf deiner Funktion aber auch ein DB-Element vom Typ UDT13 an den Parameter anlegst. Verwendest du jedoch einen UDT14, dann melden VaraintPut und VaraintGet einen Typkonflikt. Insofern hättest du eben auch gleich einen UDT13 an die Schnittstelle schreiben können. Die Sache hat aber eben doch einen Vorteil. Man kann wie die Systemfunktionen mehrere verschiedene Datentypen behandeln. Dazu legst du eben nicht nur einen Temp vom Typ UDT13 an sondern deiner Anwendung entsprechend einen t13:UDT13; t14:UDT14; t15:UDT15. Nun gibt es eine Konstrukt, mit dem man prüfen kann ob der Schnittellen input einen bestimmten Typ hat und kann man ganz gezielt mit diesem Typ weiter machen. Sieht etw so aus (ich zitiere aus dem Kopf)
Code:
if typeof(in1) = Int then
VariantGet( v1, tint );
elsif typeof(in1) = UDT13 then
VariantGet( v1, t13 );
elsif typeof(in1) = UDT14 then
VariantGet( v1, t14 );
...
Damit lässt sich dann ein begrenztes Operation-Overloading machen. Siemens macht das bei vielen Systemfunktionen vor. Einfachstes Beispiel sind MIN und MAX, trickreicheres z.B. TCON, wo man die verschiedenen Strukturen zum Aufbau einer Kommunikation angeben soll.
Man kann den Variant nicht im DB anlegen! An einer Schnittstelle ja, aber nicht DB. Also kann man ihn nicht speichern. Er lebt nur so lange der Baustein mit seiner Deklaration auf dem Stack liegt. Ist der Baustein beendet, ist der Zeiger weg.:roll: Warum ist das so? ... eine dünne Vermutung meinerseits: Download im Run. Damit verliert die Sache aber sehr viel an Reiz. Wenn ich große Datenmengen habe und mir merken will, dass damit was zu tun ist, dann kann ich den Variant genau dafür nicht verwenden. Man muss so wie S. das im Beispiel zeigt die Daten kopieren.
Der einzige Ausweg aus diesem Dilemma scheinen diese seltsamen ArrayDB zu sein, aber das ist wieder eine ganz andere Geschichte.
Seit der V13 kann man also mit dem Variant was anfangen. ABER
man muss viel zu viel Daten kopieren --> schnell ist das nicht
man kann nicht auf einzelne Elemente einer Struktur zugreifen
man kann den Variant nicht speichern
So taugt mir das nicht. Kennen die eigentlich die IEC61131-3 3rd Edition. Die dort gezeigten Referenzen, das ist das was man verwenden kann. Das kann zwar etwas weniger flexibel als Variant, ist aber trotzdem viel intuitiver.
'n schön' Tach auch
HB