SCL: Pointer auf Struct in DB

DunderHEAD

Level-1
Beiträge
17
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich würde gerne einen Zeiger auf eine Struktur in einem DB an einen FB übergeben, um die werte innerhalb der Struktur mit lokalen werten (innerhalb des FB) zu vergleichen.


// UDT:
Code:
TYPE 
sDataStr : STRUCT
            iNumAvailEntr : INT ; //[ ] number of available errer field entries 
            adiErrNumArr : ARRAY[1..100] OF DINT ; //local error numer array
        END_STRUCT;             
END_TYPE

// Global DB:
Code:
DATA_BLOCK g
    STRUCT
        sGlobStr      :   sDataStr;
    END_STRUCT
    BEGIN 
END_DATA_BLOCK

// FB, Beispiel
Code:
VAR_INPUT
    pGlobDataStr    : POINTER; //[] Pt auf g.sGlobStr
    sGlobDataStr AT pGlobDataStr : sDataStr; //für besseren zugriff
END_VAR

    //Bsp.:
    // Arbeiten mit den Werten aus der globalen Struktur
    IF ( sGlobDataStr.iNumAvailEntr > 0 ) THEN
        ...
    END_IF;


Die Frage ist nun, wie muss ich den FB aufrufen und wie müssen die Variablen/Pointer deklariert werden. Damit ich mit diesen vernünftig arbeiten kann.
Ich möchte auf die Werte in der globalen Struktur nur lesend zugreifen. Daher möchte ich nicht unbedingt eine lokale kopie im FB anlegen, wenn dies nicht unbeding nötig ist.

Vielen Dank schon mal, fürs Durchlesen und ggf. für eine hilfreiche Antwort.

MFG
DunderHEAD
 
Hallo,
der IN-Parameter deines FB muß dann auch vom Typ "sDataStr" sein - dann kann dein FB und SCL mit den eingelagerten Einzel-Variablen arbeiten (weil es sie dann kennt ...!).

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

aber dann würden die Daten ja quasi doppelt vorliegen.
- Zum Ersten im DB g
- Zum Zweiten im instanz DB von FB

Aber gerade das Anlegen der Daten (belegen von Platz) im instanz DB des FB würde ich gerne umgehen.
Da im original die Struktur doch sehr groß ist, und auch das kopieren/übergeben an den FB Zeit benötigt.
Daher ev. einen Zeiger auf die Struktur übergeben und diesen dann mit dem "AT" an eine Variable diesen Typs heften.
 
Naja ...
Das mit dem Zeiger (Pointer) geht schon mal gar nicht. Wenn du den Datenbereich an sich übergeben möchtest, dann ginge das natürlich auch per ANY-Pointer - das würde die Sache dann auch nicht besser machen, da du dir dann die Daten wirklich erst "lokal" noch einmal abbilden müßtest.

Da mein Vorschlag der einzige (im Rahmen deines Wunsches) machbare Weg ist - was spricht denn dagegen - außer dass du den UDT "sDataStr" auch dem FB bekannt machen mußt ? Du übergibst übrigens auch in dem Fall nicht den Datenbereich, sondern eine Referenz darauf ...

Gruß
Larry
 
So?

Hallo,

nunja wirklich dagegen spricht nichts.. nur das ich dann in beiden DB etliche kB Speicher belege.

Nach deinem Vorschlag müsste es dann so aussehen ja?

// UDT:
Code:
TYPE 
sDataStr : STRUCT
            iNumAvailEntr : INT ; //[ ] number of available errer field entries 
            adiErrNumArr : ARRAY[1..100] OF DINT ; //local error numer array
        END_STRUCT;             
END_TYPE
// Global DB:
Code:
DATA_BLOCK g
    STRUCT
        sGlobStr      :   sDataStr;
    END_STRUCT
    BEGIN 
END_DATA_BLOCK
// FB, +iDB als instanz DatenBaustein
Code:
VAR_INPUT
    sGlobDataStr : sDataStr; //für besseren zugriff
END_VAR

    //Bsp.:
    // Arbeiten mit den Werten aus der globalen Struktur
    IF ( sGlobDataStr.iNumAvailEntr > 0 ) THEN
        ...
    END_IF;
//PRG_CALL
Code:
FB.iDB( sGlobDataStr := g.sGlobStr);
Das würde dann doch aber auch bedeuten, dass wenn ich im FB Daten in sGlobDataStr verändere sich diese automatisch/gleichzeitig auch im DB ändern. Oder?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... bei einem IN-Parameter bin ich mir da nicht so sicher (habe ich noch nie versucht). Wenn du das haben willst, dann wäre deine Struktur am IN_OUT (also Durchgang) richtig aufgehoben ...

Gruß
Larry
 
Danke...

Dachte, dass man mit etwas weniger Speicherverbrauch auskommt... aber so ist es dann auch ok.

Dann kann ich dies jetzt ja so in mein Prog einpflegen! :ROFLMAO:

Vielen Dank für die Hilfe.
 
Ich glaube jetzt hab ich's...

Entschuldigung für den doppel Post... :rolleyes:

Jetzt habe ich es im instanz DB von FB gesehen. Wenn ich die Struktur, sDataStr, in
- Input oder
- Output
anlege, dann braucht sie den viel Speicher (Speicher für alle beinhalteten Variablen) im instanz DB.
Wenn ich die Struktur aber im Bereich
- In_Out
anlege belegt diese "nur" 6 Byte (entspricht einem Zeiger?!).

:ROFLMAO: Dann lasse ich sie jetzt im IN_Out und dann habe ich ja was ich will... :ROFLMAO:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das ist schön ...
Ich muß dir aber auch gestehen, dass ich die UDT's bislang auch immer "nur" als IN_OUT übergeben habe. Deshalb war mir deine Abneigung dagegen auch nicht wirklich klar ...

Gruß
Larry
 
Danke für der (Er)klärung...

Hallo,

wusste doch, dass ich was von 6 Byte entsprechen einem Pointer gelesen haben. :D
Sind aber nicht nur BOOL, die nicht als Pointer vorliegen.

Code:
Typ                                     Belegter Platz

BIT                                      0.1
BYTE                                    1
WORD                                   2
DWORD                                 4

INT                                      2
DINT                                    4
REAL                                    4

S5TIME                                 2
TIME                                    4
DATE                                    2
TIME_OF_DAY                        4

STRUCT                                6    <- Zeiger 
ARRAY[x..y]                           6    <- Zeiger

Die nächste Erkenntnis bzw. wissenswert für mich ist, dass STRUCT und ARRAY in den anderen Deklarations... (VAR_INPUT, VAR_OUTPUT, usw.) die tatsächliche Größe belegen und nicht 6 Byte.

VAR_INPUT Parametern kann man im aufgerufenen FB neue Werte zuweisen. Und diese dann im aufrufenden FB/OB aus dem instanz DB des FB herausholen (wie bei VAR_OUT).

VAR_IN_OUT Parameter beinhalten immer den aktuellen Wert.

VAR_OUT Parameter können einem FB beim Aufruf nicht zugewiesen werden.


------------------------------------
Test Beispiel:

UDT
Code:
TYPE UDT1
    STRUCT
            StrIn      : INT;
            StrOut     : INT;
            StrInOut   : INT;
    END_STRUCT
END_TYPE

DB
Code:
DATA_BLOCK DB1
//
// Baustein-Kommentar ...
//
    STRUCT
        gStr        : UDT1;
        
        WertIn      : INT;
        WertOut     : INT;
        WertInOut   : INT;
    END_STRUCT
BEGIN

END_DATA_BLOCK

FB
Code:
FUNCTION_BLOCK FB2


// Bausteinparameter
VAR_INPUT
    // Eingangsparameter
    WertIn  : INT;
    StrIn   : UDT1;
END_VAR

VAR_IN_OUT
    // Durchgangsparameter
    WertInOut  : INT;
    StrInOut   : UDT1;
END_VAR

VAR_OUTPUT
    // Ausgangsparameter
    WertOut  : INT;
    StrOut   : UDT1;
END_VAR


    // Anweisungsteil
    WertIn      := WertIn   + 1;
    WertOut     := WertOut  + 1;
    WertInOut   := WertInOut+ 1;
    
    StrIn.StrIn         := StrIn.StrIn          + 1;
    StrOut.StrOut       := StrOut.StrOut        + 1;
    StrInOut.StrInOut   := StrInOut.StrInOut    + 1;
    
END_FUNCTION_BLOCK

Inztanz DB zu FB
Code:
DATA_BLOCK DB2

FB2

BEGIN

END_DATA_BLOCK

OB zum Aufruf von FB
Code:
ORGANIZATION_BLOCK OB31

VAR_TEMP
    // reserviert
    info : ARRAY[0..19] OF BYTE;
    // temporäre Variablen
END_VAR  
    
    
    // Zuweisung   


    FB2.DB2(         
         WertIn     := DB1.WertIn
        ,StrIn      := DB1.gStr
        ,WertInOut  := DB1.WertInOut
        ,StrInOut   := DB1.gStr
        );
        
        DB1.WertIn := DB2.WertIN;
        DB1.gStr.StrIn := DB2.StrIn.StrIn;
        
        DB1.WertOut := DB2.WertOut;
        DB1.gStr.StrOut := DB2.StrOut.StrOut;

END_ORGANIZATION_BLOCK

Wie am Anfang gesagt, es ist ein Test. Inwieweit es Sinn mach die Parameter so zu verwenden muss man sich überlegen.

----
Aber nun habe ich doch das gute Gefühl, dass ich es begriffen habe!
War ein langer gedanken Weg von :confused: nach :ROFLMAO:.

Vielen Dank euch allen für eure Kommentare, die mich hier her gebracht haben.
 
Zurück
Oben