Struktur als Propertie

SY50

Level-1
Beiträge
271
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, wenn in einem FB eine lokale Struktur "Sollwerte" habe, die zwei Variablen enthält.
Geschwindigkeit und Position.

Kann ich dann in dem FB eine Propertie vom Typ dieser Struktur anlegen?
Wenn ja, könnte ich dann diese auch von außen so beschreiben:

FBinstanz.property.geschwindigkeit := 100.0;

Geht das? Also dass ich in der Propertie auch die Struktur behalte.
 
Reden wir von CoDeSys?

In CoDeSys werden Strukturen immer global definiert. Man kann Sie dann immer lokal und global verwenden.
Das ist dann zwar keine Property aber immerhin ein komplexer Datentyp. Den kann man natürlich innerhalb eines FB zur Typdeklaration verwenden. Das geht auch als IN oder Out Parameter, die Du dann global mit dem gleichen Typ verschalten kannst.
 
In CODESYS V3 ist Property ein Sprachelement und ich denke darum geht es.
Eines sollte man immer im Hinterkopf behalten: ein Property ist nur eine andere Schreibweise für eine Methode.
Wenn ein Property einen Rückgabewert vom Typ einer Struktur hat, dann wird die gesamte Struktur zurückgeliefert.
Das sollte man vermeiden.
Dieser Zugriff:

FBinstanz.property.geschwindigkeit := 100.0;

ist dann auch nicht erlaubt, er hätte auch nicht den gewünschten Effekt, weil der Property-Zugriff den Wert der Internen Struktur
als Kopie zurückliefert, und man dann nur den Rückgabewert manipulieren würde.

Um das zu Umgehen sollte man als Typ eines Property REFERENCE TO <STRUCT_Name> definieren. Dann wird
wirklich nur eine Referenz auf die Struktur zurückgeliefert und dann ist auch dieser Zugriff erlaubt:

FBinstanz.property.geschwindigkeit := 100.0; // hier wird direkt in die Struktur der Instanz geschrieben

Oder zweite Möglichkeit, wenn die Struktur eh nur aus zwei Elementen besteht kann man sich ja auch zwei
Properties definieren um die Elemente einzeln zu manipulieren:

FBinstanz.property_geschwindigkeit := 100.0;
 
Das glaub ich gerne, meine Erklärung war auch ein bisschen kurz. Folgendes sollte funktionieren:

Diese Struktur:
Code:
TYPE DUT :
STRUCT
	x, y : DINT;
END_STRUCT
END_TYPE

Dieser FB:
Code:
FUNCTION_BLOCK POU
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
	_dut : DUT; 
END_VAR

mit folgendem Property:
Code:
PROPERTY Prop : REFERENCE TO DUT
Das folgenden Get-Zugriff bietet: (Set-Zugriff am besten Löschen!)
Code:
Prop REF= _dut; // wichtig: REF= überschreibt eine Referenz := schreibt [U]auf[/U] die Referenz!

und schliesslich folgender Aufruf:
Code:
PROGRAM PLC_PRG
VAR
	inst : POU;
END_VAR
inst.Prop.x := inst.Prop.x + 1;
 
@Werner29
Was ist denn nun der eingentliche Unterschied von dieser Herangehensweise gegenüber einer ordinären INOUT?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
In diesem Beispiel ist überhaupt kein Unterschied.
Wenn man mit Objektorientierung arbeitet, dann kann man ein Property auch überschreiben, oder in einem Interface definieren.
Mit einem VAR_IN_OUT geht das nicht.

Das ist überhaupt die wichtigste Funktion der Properties.
Ausserdem hat man in einem Property noch die Chance programmatisch einzugreifen. Im oberen Beispiel könnte es sein, dass die Struktur
nicht zu jedem Zeitpunkt zugreifbar ist, oder dass es zwei Strukturen gibt von denen mal die eine, und mal die andere verwendet wird:

Code:
IF Heute = Montag THEN
     Prop REF=  _dut1;
ELSE
     Prop REF= _dut2;
END_IF

Von aussen schaut das dann wie eine Variable aus, obwohl der FB mal das eine mal das andere zurückliefert.
Meistens wird sowas in komplexen Bibliotheken gemacht.
 
Wieso muss ich die Set löschen? Ps. In deinem Beispiel schreibst du doch auf die Propertie, brauchst du da nicht die Set?
 
Der Aufrufer der GET-Methode hält ja als Ergebnis eine Referenz auf den internen Wert, und mit dieser Referenz kann er dann alles machen, insbesondere auch schreiben.
Ein schreiben per SET auf einen Referenztyp würde bedeuten, die Referenz zu überschreiben (also würde die Referenz auf ein anderes Datum zeigen), das will man aber nicht.
 
Wie ich das verstehe

Also wird die get-Methode auch aufgerufen, wenn die Propertie auf der linken Seite des := steht? Ich dachte dann wirkt immer die Set-Methode. ???

Ich verstehe die Aussage so:

Um den Wert zuweisen zu können, braucht man die Adresse, an die der Wert gepackt wird.

Das liefert die GET Funktionalität, die liefert die Referenz. Auf diese Referenz wird dann der Wert geschrieben.

Diese ganze Zeigerei ist in ST sehr unübersichtlich, Pascal wollte im Gegensatz zu C möglichst ohne Zeiger auskommen, später hat man dann gemerkt, dass man doch so etwas gerne hätte und die Semantiker mussten gewaltige Klimmzüge machen.

Es ist schade, dass man sich nicht endlich einmal mit der neuen ST Spracherweiterung an aktuelle Entwicklungen in der Notation angepasst hat.

Was dem FB fehlt aus meiner Sicht, ist der Schritt zum echten Objekt mit Constructor und mit gettern/settern und Methoden. Wenn man dann noch von C# das Referenz Modell incl. Notation übernehmen würde, könnte man die Pointer abschaffen und hätte eine inhärent sichere und effektive Sprachimplementation gewonnen.
 
RobiHerb hat recht, aber ich sags nochmal in meinen Worten:

Wir haben es ja hier mit einem Referenz-Zugriff zu tun, intern entspricht das folgendem Code mit Pointer:

instanz.pstruct^.a := instanz.pstruct^.a + 1;

der Pointer selbst wird hierbei ja auch nicht geschrieben, der ist auf der linken und der rechten Seite der Zuweisung der gleiche,
und verändert sich durch die Zuweisung nicht. Es wird nur die Variable a geschrieben.
Wenn das Property einen Pointer zurückliefern würde, wäre die Sache vermutlich klar:

So würde das SET-Property aufgerufen:
inst.pstruct := ADR(irgendwas);
In dem Fall könnte der Pointer auch NULL sein, der alte Wert interessiert nicht.

So wird aber das GET-Property aufgerufen:
inst.pstruct^ := irgendwas;
In dem Fall würde es zu einer Exception kommen, wenn der Pointer NULL ist.

Ich gebe gern zu dass das ganze verwirrend ist, aber wie gesagt, ich kenne solchen Code vor allem aus Bibliotheken.
Die Komplexität liegt in der richtigen Definition des Property. Der, der das Property benutzt muss sich dann
nicht mehr darum kümmern, ob er hier direkt einen Wert bekommt, oder eine Referenz, oder ob der SET oder GET-Accessor
aufgerufen wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es ist schade, dass man sich nicht endlich einmal mit der neuen ST Spracherweiterung an aktuelle Entwicklungen in der Notation angepasst hat.

Was dem FB fehlt aus meiner Sicht, ist der Schritt zum echten Objekt mit Constructor und mit gettern/settern und Methoden. Wenn man dann noch von C# das Referenz Modell incl. Notation übernehmen würde, könnte man die Pointer abschaffen und hätte eine inhärent sichere und effektive Sprachimplementation gewonnen.

Sprichst du von CODESYS V3 oder von IEC 61131-3 3rd Edition?
Also ein Konstruktor ist schon praktisch, haben wir im Moment nur eingeschränkt (FB_Init), in der 3rd Edition steht so was nicht, wird aber auch nicht ausgeschlossen.
Das C# Referenzmodell lebt halt auch vom garbage collector, und dieser ist auf einer SPS mit Echtzeitanforderungen nur schwer zu implementieren.
Die statisch allozierten FBs der 61131-3 haben den Vorteil, das nie die Referenz auf ein Objekt verloren gehen kann, und dass der Speicher zur Laufzeit
nie ausgehen kann. Man muss einen Kompromiss finden.

Nachsatz: eine FB_Instanz ist auch nie NULL.
 
Habe ein Problem mit den Namen der Properties.
Ich habe eine Variable namens Direction. Habe auch eine Property Namens Direction erstellt.
Nun möchte ich im Getter diese zuweisen. Wenn ich dort nun Dircetion eingebe, dann bekomme ich in der Autovervollständigung nur die Vriable angezeigt. nicht die Property.
Gibt es da ne Möglichkeit diese auch dort hin zu bekommen? Oder muss die Property anderst heisen? Das wäre natürlich etwas blöd :-(
 
Beide sind lokal bekannt? Dann gibt es ja auch eine Verschattungsregel, vermutlich verschattet die Variable das Property und deshalb kann auch nur eines von beiden verwendet werden.
Also genauso wie man nicht zwei lokale Variablen gleich nennen kann, kann man auch nicht ein Property so nennen wie eine lokale Variable.
Beide teilen sich einen Namensraum.
 
Ich persönlich beginne meine lokalen Variablen immer mit _var, dann erkenne ich das auch auf den ersten Blick.
In den meisten Firmen gibt es ja spezielle Richtlinien zur Namensgebung.
 
Zurück
Oben