Using Simulink® Strings
Simulink® strings are explicitly allowed and can be used with the TwinCAT Target for Simulink®.
Restriction
Depending on the MATLAB® release version, code interface packaging setting and the set C/C++ standard, Simulink® Coder™ compiles a Simulink® string into the std::string
data type.
If this Simulink® string is used as model input or model output, it should be noted that these entries cannot always be connected to other objects in TwinCAT by mapping. Mapping in TwinCAT assumes a static data type size, which is not the case with std::string
.
Detailed sample in MATLAB® The topics for TwinCAT Build 4024 and 4026 are described in detail in this sample:
|
Handling with TwinCAT 3.1 Build 4026
The TwinCAT SDK for TwinCAT Builds >=4026 allows the use of a std::string
implementation. This means that strings can also be implemented in mapping.
This option has two restrictions:
- The std::string elements used as local variables in the functions generated by Simulink® Coder™ can increase the required stack size because the std::string data is on the stack.
- The maximum string size at compile time is limited to a value selected by the user. For example, if the generated code concatenates two strings that exceed the size, an exception occurs. Please design your model accordingly and validate it, for example by code checking, to ensure that this does not happen.
Use the following settings to successfully build the Simulink® model:
set_param(modelName,'TcProject_CppLanguageStandard','stdcpp20');
set_param(modelName,'TcProject_UseStaticStlString','on');
The size of the underlying character array is set to 256 by default, as configured by the Simulink® parameter DynamicStringBufferSize.
If desired, the size of the underlying character array can be set independently of the Simulink® parameter DynamicStringBufferSize via the project parameter StaticStlStringCapacity:
set_param(modelName,'TcProject_StaticStlStringCapacity','255');
For the TcCOM data areas, the corresponding TwinCAT type for each std::string is a structure type with a data member and a size member. If a string value is set, both the data member and the size member must be set. The size is the length of the character array that will be set to the data value and can be between 0 and the value of StaticStlStringCapacity. Selecting a value greater than StaticStlStringCapacity results in undefined behavior.
The usability of the PLC-FB is similar to the TcCOM module, where std::string is a structure with a size member and a data member. Writing a string value requires both the size member and the data member to be set, while reading a string value may require the user to truncate the string read from the data element to the appropriate size.
Handling with TwinCAT 3.1 Build 4024
So that you can still use the inputs and outputs, it is recommended that the PLC-FB (no mappings necessary) or the TcCOM Wrapper FB are used. For the standard inputs and outputs of the FBs, the Simulink® string entries are not displayed in either case. These are to be set separately via getter and setter methods on the FB.
Simulink® bus with Simulink® strings: restricted use The following situation is currently not supported: a Simulink® string cannot be used in a Simulink® bus that serves as input or output of the model if it is mapped as |
Sample
Let's take the following Simulink® model with a mixture of string and non-string inputs and outputs.
When this model is compiled with MATLAB® R2022a and “C++ Class” code interface packaging, the data type std::string
is generated by Simulink® Coder™. In the following figure, it can be seen that the string inputs and outputs are not present in the process image in TwinCAT.
Only the non-string inputs and outputs are present in the process image.
To be able to write and read the strings, either the TcCOM Wrapper FB or the PLC FB must be used. Corresponding getter and setter methods are automatically created at the function blocks.
Sample code using the PLC-FB:
VAR
fbStringSample : FB_string_sample;
myStringIn : T_MaxString;
myStringOut1 : T_MaxString;
myStringOut2 : T_MaxString;
nSize : ULINT;
nSize2: ULINT;
fIn : LREAL;
fOut : LREAL;
END_VAR
// put sting input
fbStringSample.put_StringInput(c_str := ADR(myStringIn));
// call function
fbStringSample(fNonStringInput := fIn, fNonStringOut3 => fOut);
// get string outputs
nSize := SIZEOF(myStringOut1);
fbStringSample.get_StringOut1(c_str := ADR(myStringOut1), size := nSize); // size in VAR IN OUT!
nSize2 := SIZEOF(myStringOut2);
fbStringSample.get_StringOut2(c_str := ADR(myStringOut2), size := nSize2);