verschachtelte Übergabe von Variablen (Datenstrukturen)

jasper

New member
Beiträge
2
Punkte Reaktionen
0
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo zusammen,

ich habe ein Programmierproblem und hoffe, dass mir hier vielleicht jemand einen Lösungstip gibt.

(Programmiert wird in Step 7 mit SCL)


Ich versuche mal mein Problem zu schildern :

In einem Global-DB sind mehrere UDT-Variablen gespeichert, der UDT fasst mehere Eigenschaften eines Objektes zusammen.

Aus dem OB1 wird ein FB aufgerufen und als In_Out-Paremter wird eine (UDT-)Variable aus dem Global-DB übergeben.
In dem FB wird jetzt die Variable verändert. Nach dem FB Aufruf steht jetzt im Global-DB die veränderte Variable zur Verfügung.
Soweit funktioniert alles wie gewünscht.

Jetzt sollen einzelne Funktionen zur Manipulation der Variable in einen FC ausgelagert werden.
D.h. im FB wird jetzt ein FC aufgerufen, dem wieder als In_Out_Parameter die (Struktur)Variable übergeben werden soll.
Allerdings wird der Versuch die SCL-Quelle zu übersetzen, mit der Fehlermeldung "Parameterübergabe nicht korrekt" abgebrochen.

Als erste Hilfe wird jetzt die dem FB übergebene Variable in eine lokale Variable des FB kopiert, diese lokale Variable dem FC übergeben und am Ende die lokale Variable wieder zurück in die übergebene kopiert.

Das Funktioniert zwar, ist aber natürlich nicht sehr elegant und bläht den Instanz-DB unnötig auf, da es jetzt die Variablen ja quasi doppelt gibt.

Hoffentlich ist die Erklärung so halbwegs verständlich, und einer von euch kann mir bei der Lösung helfen.

MfG
Jasper
 

Blockmove

Supermoderator und User des Jahres 2019
Teammitglied
Beiträge
10.386
Punkte Reaktionen
3.028
Die Übergabe an den FB mit InOut ist nur eine Referenz. Deshalb kannst du sie - meines Wissens - nicht im FB an die FC weitereichen.
Ich löse solche Aufgaben auch immer mit einer lokalen Kopie. Frisst zwar Speicherplatz, ist aber übersichtlich und nachvollziehbar.

Du kannst das "Problem" vielleicht übergehen indem du Any-Pointer zur Übergabe nutzt.
Daraus kannst du dann die Adressen im Global-DB ermittlen.

Gruß
Dieter
 

PN/DP

User des Jahres 2011-2013; 2015-2017; 2020-2021
Beiträge
19.493
Punkte Reaktionen
5.876
Zuviel Werbung?
->Hier kostenlos registrieren
Egal ob SCL oder AWL oder ... - das Durchreichen eines zusammengesetzten Datentyps von IN_OUT ist nicht möglich.
Es geht nur per Umkopieren über eine bausteineigene Variable (TEMP oder STAT).

Nachteil bei einer Übergabe per ANY-Pointer: die Symbolik und die Datentypen gehen verloren. Deshalb müsste man erst wieder auf einen lokalen UDT kopieren. Und der ANY selber muß zum Durchreichen auch erst kopiert werden. Und man muß selber darauf achten, daß der am ersten Baustein übergebene STRUCT nicht in TEMP liegt.

bläht den Instanz-DB unnötig auf
Lege die lokale Kopie der Variable in den TEMP-Bereich, dann vergrößert es nicht den Instanz-DB.

Harald
 

Blockmove

Supermoderator und User des Jahres 2019
Teammitglied
Beiträge
10.386
Punkte Reaktionen
3.028
Lege die lokale Kopie der Variable in den TEMP-Bereich, dann vergrößert es nicht den Instanz-DB.

Damit hab ich heut selber einen Griff ins Klo getätigt ... Man muß dabei natürlich Schachtelungstiefe und max. Lokaldatengröße beachten.
Da ich den Instanz-DB in diesem Fall nicht bei laufender Anlage ändern konnte, bin ich entgegen meiner Gewohnheit auf Lokaldaten ausgewichen.
Tja, manchmal verliert man und manchmal gewinnen die anderen :cry:

Gruß
Dieter
 
OP
J

jasper

New member
Beiträge
2
Punkte Reaktionen
0
Hallo zusammen,

vielen Dank für eure Antworten und Unterstützung.

Mit dem vermeintlichem "Notbehelf", dem kopieren in eine lokale-Variable, lebe ich jetzt schon länger.
Jetzt wo ein neues größeres Projekt vor der Tür steht, sollten die FBs mal aktualisiert werden und dieses Kopieren erschien mir schon länger als nicht optimale Lösung.

Ein kopieren in den Temp-Bereich kommt leider nicht in Frage.

MfG
Jasper
 

LinusAM4V

Well-known member
Beiträge
77
Punkte Reaktionen
39
Hallo zusammen.
Ich hätte eine Lösung des Problems anzubieten. Allerdings nur für AWL. Ob dies auch in SCL möglich ist, kann ich nicht
sagen. Hierzu sollte sich dann einer unserer SCL Spezialisten äußern.
Nun aber:
Wenn wir einen FB haben, der einen INOUT vom Typ UDT besitzt, so wird dieser wie alle anderen Parameter im IDB des FB
abgelegt. Da es ein INOUT ist, wird allerdings nicht die ganze Struktur, sondern nur ein Pointer abgelegt, und dieser übergeben.
Wird in diesem FB nun ein FC aufgerufen, der ebenfalls einen INOUT vom Typ UDT besitzt, kann dieser Pointer nicht direkt an den
FC weitergegeben werden. Beim FC CALL wird ein Pointer aufgebaut. Dieser sollte nun den Inhalt des FB Pointers bekommen, nicht aber
einen Pointer auf einen Pointer bilden. Dies ist der Grund, warum ich diesen Parameter nicht weitergeben kann.
Die Lösung ist nun, dem FC einen Pointer zu geben, der nicht auf einen Pointer zeigt, sondern den Inhalt des FB Pointer enthält.
Dies kann allerdings nur über eine AWL Quelle programmiert werden, da ein UC Call mit Parametern nicht im Editor versorgt werden kann.
Code:
FUNCTION_BLOCK FB 1
VAR_IN_OUT
  IN_OUTUDT : UDT 1; 
END_VAR
VAR_TEMP
  VKE_SPEICHER : BOOL;
  AR1_SPEICHER : DWORD;
  AR2_SPEICHER : DWORD;
  POINTER_DB   : WORD;
  POINTER_ADDR : DWORD;
END_VAR
BEGIN
NETWORK
      =     VKE_SPEICHER;
      TAR2  AR2_SPEICHER; 
      TAR1  AR1_SPEICHER; 
      L     P##IN_OUTUDT;
      LAR1;
      L     DIW [AR1,P#0.0]; 
      T     POINTER_DB; 
      L     DID [AR1,P#2.0]; 
      T     POINTER_ADDR; 
      LAR1  AR1_SPEICHER;
      
      UC    FC     1 { P#POINTER_DB };
      LAR2  AR2_SPEICHER;
END_FUNCTION_BLOCK
Dies ist nun der FB, der den FC aufruft.
Dabei wird aus dem IDB des FB der Inhalt des Pointers in einen temporären Pointer des LSTACK des FC aufgebaut.
Da im TEMP Bereich kein Pointertyp projektiert werden kann, wird der Pointer getrennt definiert.
Das AR2 Register muss vorher gesichert und nach dem UC wieder restauriert werden. Das AR1 wird kurzfristig benutzt und wieder
restauriert.
Hiermit wird nur ein Pointer übergeben, es muss nicht die ganze Struktur umkopiert werden.
Alle Adressen sind nicht absolut sondern relativ verwendet.
Daher sollte dieses Beispiel allgemeingültig sein!
Da ein Pointer auf den IDB geladen wird, ist dieses Beispiel noch NICHT multiinstanztauglich.
In diesem Fall muss noch das AR2 Register berücksichtigt werden.
VORSICHT!
Wenn der FC1 ausser dem UDT noch weitere Parameter besitzt, müssen diese für den UC Call in korrekter Form
übergeben werden! Dies ist hier nicht beschrieben!
mfg
Linus
 

Blockmove

Supermoderator und User des Jahres 2019
Teammitglied
Beiträge
10.386
Punkte Reaktionen
3.028
Zuviel Werbung?
->Hier kostenlos registrieren
Wie sieht das ganze eigentlich in AWL nach dem überstetzen aus?
Ist der "Trick" nur, dass in AWL-Quellen der Editor die Parameter beim Einfügen eines FCs nicht einfordert?

Gruß
Dieter
 

LinusAM4V

Well-known member
Beiträge
77
Punkte Reaktionen
39
Hallo Blockmove.
Der Umweg über die Quelle ist notwendig, um den Parameter am UC anzuparametrieren.
In AWL sieht der Call dann identisch der Quelle aus.
Der Call selber hat dann auch 2 Zeilen:

UC FC1
P#L10.0

Die zweite Zeile ist mit dem Editor nicht machbar, und sollte auch nicht versucht werden zu editieren!
mfg
Linus
 

Draco Malfoy

Well-known member
Beiträge
1.168
Punkte Reaktionen
80
Hat Firma Siemens sich mal wieder in einmaliger Form ins Knie geschossen.
Wieso ZUM GEIER kann ich denn nicht einfach einen ANY-Pointer dereferenzieren und an die Schnittstelle des unterlagerten Bausteins dranschreiben ??
 
Oben