Hi,
I define the following struct in plcnext
MonElement : Struct
CurrentA : INT;
End_Struct;
StuctWithStruct:STRUCT
Repetition:UINT;
Valid:BOOL;
OneStruct:MonElement;
END_STRUCT;
With the following code, the 2 first element of the struct is correcty written. The struct element is not updated but the service don't issue any error (return code is DataAccessError::None
Arp::Plc::Gds::Services::WriteItem structItem;
structItem.PortName = "Arp.Plc.Eclr/SwS";
structItem.Value = RscVariant<512>::CreateStructVariant(3);
dataItems.WriteNext(structItem);
// Create an RscStructWriter for the struct
RscStructWriter<512> structWriter{ structItem.Value };
structWriter.WriteNextField((Arp::uint16)1);
structWriter.WriteNextField((Arp::boolean)true);
//ajout du tableau de structure de 20 element de 3 membres
RscVariant<512> OneStruct = RscVariant<512>::CreateStructVariant(1);
// Write the array item to the enumerator *before* creating the RscArrayWriter
structWriter.WriteNextField(OneStruct);
RscStructWriter<512> structWriter2{ OneStruct};
structWriter2.WriteNextField((Arp::uint16)2);
dataItems.EndWrite();
With a tab in a struct with the following declaration and code the error returned is typeMismatch,
Struct declaration in plc next:
TabUINT : Array [0..1] of UINT;
StuctWithTab:STRUCT
Repetition:UINT;
Valid:BOOL;
OneTab:TabUINT;
END_STRUCT;
Arp::Plc::Gds::Services::WriteItem structItem;
structItem.PortName = "Arp.Plc.Eclr/SwT ";
structItem.Value = RscVariant<512>::CreateStructVariant(3);
dataItems.WriteNext(structItem);
// Create an RscStructWriter for the struct
RscStructWriter<512> structWriter{ structItem.Value };
structWriter.WriteNextField((Arp::uint16)1);
structWriter.WriteNextField((Arp::boolean)true);
//Add array of 2 uint16
RscVariant<512> OneTab = RscVariant<512>::CreateArrayVariant(2, RscType::Uint16);
// Write the array item to the enumerator *before* creating the RscArrayWriter
structWriter.WriteNextField(OneTab);
RscArrayWriter ArrayWriter{ OneTab };
ArrayWriter.WriteNext((Arp::uint16)1);
ArrayWriter.WriteNext((Arp::uint16)2);
dataItems.EndWrite();
As their is no sample of writing Struct containing array or other struct is my code correct or is a problem somewhere?
Regards
Sorry for the delay.
Regarding the second issue - a structure containing an array - I can’t see what the problem is in your code.
This works for me (AXC F 2152 FW 2022.6, Toolchain version 2022.0, PLCnext Engineer version 2022.6):
**PLCnext Engineer types**
UINT_ARRAY_0_9 : ARRAY[0..9] OF UINT;
STRUCT_TYPE3 : STRUCT
MyBoolean : BOOL;
MyUInt16 : UINT;
MyFloat32 : REAL;
MyString : STRING;
MyArray : UINT_ARRAY_0_9;
END_STRUCT
PLCnext Engineer global variable declarationimage.pngC++ code
// Write the Struct port name and value
// Create the RscVariant representing the struct, with five fields
Arp::Plc::Gds::Services::WriteItem structItem;
structItem.PortName = "Arp.Plc.Eclr/Globby3";
structItem.Value = RscVariant<512>::CreateStructVariant(5);
// Write the struct item to the enumerator *before* creating the RscStructWriter
dataItems.WriteNext(structItem);
// Create an RscStructWriter for the struct
RscStructWriter<512> structWriter{ structItem.Value };
// Fill the RSC Struct Variant with values
// The fields are written in the order that they are declared
structWriter.WriteNextField((Arp::boolean)true);
structWriter.WriteNextField((Arp::uint16)42);
structWriter.WriteNextField((Arp::float32)42.31);
// Create an RscString variable to write to the next struct element
// IMPORTANT: The maximum size of the RscString MUST be the same as the maximum string size of the RscStructWriter object,
Arp::System::Rsc::Services::RscString<512> myString("String from C++");
structWriter.WriteNextField(myString);
// Create an RscVariant for the array field
RscVariant<512> arrayField = RscVariant<512>::CreateArrayVariant(10, RscType::Uint16);
// Write the field to the struct
structWriter.WriteNextField(arrayField);
// Get an array writer
RscArrayWriter arrayFieldWriter{ arrayField };
// Fill the RSC Array Variant with RscType::UInt16 values
arrayFieldWriter.WriteNext((Arp::uint16)42);
arrayFieldWriter.WriteNext((Arp::uint16)142);
arrayFieldWriter.WriteNext((Arp::uint16)242);
Resultimage.png
I will look into the other issue you mentioned.
Hi Martin , i tested your code and finally find the mistake on mine.
structItem.PortName = "Arp.Plc.Eclr/SwT ";
The trailing withespace on the portname is the cause of the problem but think the Error code returned by API must be Arp::Plc::Gds::Services::DataAccessError::NotExists and not Arp::Plc::Gds::Services::DataAccessError::TypeMismatch.
Just coming back to the first issue in your original question - a structure containing a structure.
I am afraid that once again I can’t see what the problem is in your code.
This works for me (AXC F 2152 FW 2022.6, Toolchain version 2022.0, PLCnext Engineer version 2022.6):
PLCnext Engineer types
STRUCT_TYPE4 : STRUCT
MyInt16 : INT;
END_STRUCT
STRUCT_TYPE5 : STRUCT
MyBoolean : BOOL;
MyUInt16 : UINT;
MyFloat32 : REAL;
MyString : STRING;
MyStruct : STRUCT_TYPE4;
END_STRUCT
PLCnext Engineer global variable declarationimage.pngC++ code
// Write the Struct port name and value
// Create the RscVariant representing the struct, with five fields
Arp::Plc::Gds::Services::WriteItem structItem;
structItem.PortName = "Arp.Plc.Eclr/Globby5";
structItem.Value = RscVariant<512>::CreateStructVariant(5);
// Write the struct item to the enumerator *before* creating the RscStructWriter
dataItems.WriteNext(structItem);
// Create an RscStructWriter for the struct
RscStructWriter<512> structWriter{ structItem.Value };
// Fill the RSC Struct Variant with values
// The fields are written in the order that they are declared
structWriter.WriteNextField((Arp::boolean)true);
structWriter.WriteNextField((Arp::uint16)42);
structWriter.WriteNextField((Arp::float32)42.31);
// Create an RscString variable to write to the next struct element
// IMPORTANT: The maximum size of the RscString MUST be the same as the maximum string size of the RscStructWriter object,
Arp::System::Rsc::Services::RscString<512> myString("String from C++");
structWriter.WriteNextField(myString);
RscVariant<512> structField = RscVariant<512>::CreateStructVariant(1);
structWriter.WriteNextField(structField);
RscStructWriter<512> structFieldWriter{ structField };
// Fill the RSC Struct Variant with an RscType::Int16 value
structFieldWriter.WriteNextField((Arp::int16)42);
Resultimage.png
Martin thanks for you help, i don’t change my code but after trying yours mine is working without any code change.