# Any-Pointer zum Kopieren von Strings (SCL)



## volu (14 Juni 2012)

Hallo zusammen,

ich stolpere gerade über das Kopieren von Strings....

Innerhalb meines Programms greift ein instanziierter FB auf einen während der Laufzeit festgelegten DB mit mehreren Strings zu (Array von 20 Strings zb).
Einer dieser Strings wird dann herausgelesen (Anhand der Variable #Code) und modifiziert . Das klappt soweit mit folgendem Programmausschnitt:


```
// Any-Pointer auf Vorlage
#Zeiger_Bestandteile_Vorlage.ANY_ID:= b#16#10;
#Zeiger_Bestandteile_Vorlage.Datentyp:=b#16#13;
#Zeiger_Bestandteile_Vorlage.Laenge:=w#16#1;
#Zeiger_Bestandteile_Vorlage.DB_NR:=BLOCK_DB_TO_WORD(#Vorlagen_DB);                
#Zeiger_Bestandteile_Vorlage.Anfangsadresse:=(DW#16#84000000 OR INT_TO_DWORD((#Code-1)*256*8));

// Kopieren in Puffer
#Zustand_BLKMOV:= BLKMOV(SRCBLK:=#Zeiger_String_Vorlage, DSTBLK=>#Textpuffer);
```

An diesen Puffer hänge ich noch nen Zeitstempel und paar andere Zeichen und gebe das ganze als String aus. 
Nun wundere ich mich warum das ganze nicht so abgeändert werden kann, dass der so generierte String in einen anderen, ebenfalls zur Laufzeit erst ausgewählten DB geschrieben wird.

Mein Versuch bisher:
(Ziel_DB besteht aus 20 Strings, Meldungsnummer wird mit 1 initialisiert und kann 20 nicht überschreiten)


```
// Any-Pointer auf Zielstring in Ziel_DB initialisieren
    #Zeiger_Bestandteile_Zielstring.ANY_ID:= b#16#10;
    #Zeiger_Bestandteile_Zielstring.Datentyp:=b#16#13;   // Alternativ 02
    #Zeiger_Bestandteile_Zielstring.Laenge:=w#16#1;       // Alternativ 256
    #Zeiger_Bestandteile_Zielstring.DB_NR:=BLOCK_DB_TO_WORD(#Ziel_DB);
    #Zeiger_Bestandteile_Zielstring.Anfangsadresse:=(DW#16#84000000 OR INT_TO_DWORD((#naechste_freie_Meldungsnummer-1)*256*8));

// Kopieren in Ziel_DB
   #Zustand_BLKMOV:= BLKMOV(SRCBLK:= #Meldung_Generieren_Instance.Meldung,
                                            DSTBLK=> #Zeiger_Zielstring);
```

Das byte-weise Kopieren lieferte ebenfalls den Fehlercode 837F zurück:



> Falls der tatsächlich vorhandene Ziel- oder Quellbereich kleiner als ein am Parameter SRCBLK oder DSTBLK angegebener Ziel- oder Quellbereich ist, hängt das Verhalten vom CPU-Typ ab:
> 
> Für S7-300-CPUs gilt:
> Es werden keine Daten übertragen. Am Parameter RET_VAL wird der Fehlercode W#16#837F87F
> ausgegeben.



Muss ich die Länge des erzeugten Strings herausfinden um ihn korrekt kopieren zu können?
oder greife ich auf Datenbereiche zu, die für BLKMOV nicht freigegeben sind? (Source-Block ist Ausgang eines inkludierten FBs)

Vielen Dank schon mal fürs Durchlesen, 
würde mich über Hilfe/Tipps freuen


----------



## Ralle (14 Juni 2012)

Ich verstehe nur zum Teil, was genau geht und was nicht geht.
Blockmove arbeitet zwar auch mit Strings, aber ich würde byteweises kopieren vorziehen.
Ist die Stringlänge im Kopf des String (ersten 2 Byte) korrekt, nachdem die zusätzlichen Daten angehängt wurden, nutzt du dazu die Bausteine aus der Library (concat)?


----------



## volu (14 Juni 2012)

ja ich nutze concat
 den ersten block-move habe ich zuerst byteweise vorgenommen, sodass der header zu sehen war.


----------



## Ralle (14 Juni 2012)

Ich sehe kein Source-Block. Ein wenig mehr Code hilft evtl. beim Verstehen, was genau du tust. Bei zusammengesetzten Typen an FB-IN, -OUT, -INOUT, wird nur ein Pointer übergeben. Über diesen muß man sich dann erst den Pointer auf den String holen, auf eine interne (temp) Any kopieren und dann mit dieser die tatsächlichen Daten umkopieren.


----------



## volu (14 Juni 2012)

Ok danke, genau so etwas habe ich in meinem Fall.

SRCBLK:= #Meldung_Generieren_Instance.Meldung;

Meldung_Generieren_Instance ist der Name des inkludierten FBs, bei Meldung handelt es sich um den generierten String. 
Den speicher ich morgen dann mal um und schaue was passiert, heute kann ich leider nicht mehr testen.

Vielen Dank


----------



## Ralle (14 Juni 2012)

Bin mir nicht ganz sicher, ob wir uns richtig verstanden haben, aber es ist wirklich ein recht schwieriges Thema. Daher wäre ein wenig mehr Code hilfreich.

Zum Test würde ich auf jeden Fall zuerst einmal statt

SRCBLK:= #Meldung_Generieren_Instance.Meldung;

SRCBLK mit einem fest zugewiesenen String versorgen (temp oder Stat, dort zur Laufzeit etwas hineinschreiben, wenn das geht , dann auf diesen festen String einen Any zeigen lassen und es damit testen.
Geht das, würde ich anschließend vor dem BKLMOV #Meldung_Generieren_Instance.Meldung auf den oben genutzten String umkopieren.


----------



## volu (15 Juni 2012)

Guten Morgen,

ich habe dich verstanden 


```
#Generierte_Meldung:=#Meldung_Generieren_Instance.Meldung ;
          #Zustand_BLKMOV:= BLKMOV(SRCBLK:= #Generierte_Meldung,DSTBLK=> #Zeiger_Zielstring);
```

Das Umspeichern musste in eine statische Variable erfolgen, temporäre waren schon voll.
In "Generierte_Meldung" steht dann praktisch das was drin stehen soll. 
Jedoch hat BLKMOV noch den gleichen RETVAL, deswegen vermute ich dass ich beim Any-Pointer einen Fehler gemacht habe.


```
#Zeiger_Bestandteile_Zielstring.ANY_ID:= b#16#10;
    #Zeiger_Bestandteile_Zielstring.Datentyp:=b#16#13; // String
    #Zeiger_Bestandteile_Zielstring.Laenge:=w#16#1;  // 1 String
    #Zeiger_Bestandteile_Zielstring.DB_NR:=BLOCK_DB_TO_WORD(#Error_Msg_DB);
    #Zeiger_Bestandteile_Zielstring.Anfangsadresse:=(DW#16#84000000 OR INT_TO_DWORD((#naechste_freie_Meldungsnummer-1)*256*8));                         
                                                                                                                      //Länge eines Strings: 256*8Bit
```
    Zum Überlauf von Integer kann es erst ab 33 Meldungen kommen. Diese sind jedoch auf 20 begrenzt.


----------



## volu (15 Juni 2012)

Fehler gefunden....
es lag am Any-Pointer... die AT-Sicht auf den Pointer war nicht richtig deklariert.

Den String kann ich jetzt übrigens direkt verwenden und muss nicht erst umspeichern.
Danke trotzdem für deine Hilfe!


----------

