Skip to main content

Information for Experts

Note

In CODESYS versions before 3.5.18.0, you do not have the possibility to use UTF-8 encoded variables of type STRING and the Generic String Base library. This is only possible in version 3.5.19.50 and higher. You can still use the other libraries from the CODESYS String Libraries package. However, the handling of UTF-8 encoded memory areas (for example, of type ARRAY OF BYTE) is somewhat more complicated there.

Example 7. BEFORE SP18
VAR
    abyValue : ARRAY[0..33] OF BYTE := [ // UTF-8 CØD€šŸŠ ïß värÿ çôõl
        16#43, 16#C3, 16#98, 16#44, 16#E2, 16#82, 16#AC, 16#C5, 16#A1, 16#C5, 16#B8,
        16#C5, 16#A0, 16#20, 16#C3, 16#AF, 16#C3, 16#9F, 16#20, 16#76, 16#C3, 16#A4,
        16#72, 16#C3, 16#BF, 16#20, 16#C3, 16#A7, 16#C3, 16#B4, 16#C3, 16#B5, 16#6C, 0
    ];
    myString : STR.UTF8Literal := (psValue:=ADR(abyValue));
END_VAR

As soon as UTF-8-encoded variables of type STRING are available, the above example is simplified even more:

VAR
    myString : STR.UTF8Literal := (psValue:=ADR(UTF8#'CØD€šŸŠ ïß värÿ çôõl'));
END_VAR


Conversion from STRING to IString

The data structure for managing the properties of a string segment is implemented by means of the STR._UTF8String function block. To do this, you need to allocate memory for an instance of this function block and for the string segment itself.

A function block instance must be located in a memory area which is aligned to an __XWORD address.

Example 8. Conversion from String to IString
VAR CONSTANT
    c_udiLength : UDINT := MAX(4, 512); // String segment capacity including terminal NULL
    c_udiXWORD : UDINT := SIZEOF(__XWORD);
    c_udiMaxIndex : UDINT := (SIZEOF(STR._UTF8String) + c_udiLength +  c_udiXWORD  - 1) / c_udiXWORD;
END_VAR
 
VAR
    abyValue : ARRAY[0..33] OF BYTE := [ // UTF-8 CØD€šŸŠ ïß värÿ çôõl
        16#43, 16#C3, 16#98, 16#44, 16#E2, 16#82, 16#AC, 16#C5, 16#A1, 16#C5, 16#B8,
        16#C5, 16#A0, 16#20, 16#C3, 16#AF, 16#C3, 16#9F, 16#20, 16#76, 16#C3, 16#A4,
    16#72, 16#C3, 16#BF, 16#20, 16#C3, 16#A7, 16#C3, 16#B4, 16#C3, 16#B5, 16#6C, 0
	];
    axwMemory : ARRAY[0..c_udiMaxIndex] OF __XWORD;
    udiSize : UDINT;
    itfString : STR.IString := STR.CreateString(
        ADR(axwMemory), SIZEOF(axwMemory),
        ADR(abyValue),
        udiStrSize=>udiSize
    );
    xOk : BOOL;
END_VAR
 
xOk := (
    udiSize >= 512 AND
    itfString.Len() = 33 AND
    STR.RuneCount(itfString) = 20 AND
    itfString.IsValid() AND
    NOT itfString.IsASCII()
);

With the help of the Generic String Base library, many of these requirements are taken into account by corresponding function blocks, and as a result relieving the user of many tasks. Above all, the correct reservation and alignment of the memory are encapsulated in the corresponding function blocks.