Hi! I’m developing a Csv parser in C++ to be used in AXC F 2152 (FW 2019.6). I already have the program developed but I’m getting an error because of an array of arrays of structures port definition. What I have is a typedef for the structure, typedef for the first array and a typedef for the second one. The error that the compiler is getting is:
The data type ‘arrPlant’ is not known. For ports and port structures only known data types can be used.
Definition summary:
typedef struct typedef struct { int16 iModbusType; // E_MODE uint16 uiSlaveNo; // E_ADDRESS int16 iFc; // E_FUNCTION uint16 uiAddress; // E_BASE_REGISTER int16 iQtyRegs; // E_NUM_OF_REGISTERS int16 iOpcUaIndex; // E_OPCUA_INDEX } strSingleData;
typedef strSingleData arrNetwork[500];
typedef arrNetwork arrPlant[4]; … //#port //attributes(Output|Opc|Proficloud) //#name(arrPlant) arrPlant arrayPlant;
I’ve read https://www.plcnext-community.net/index.php?option=com_content&view;=article&id;=246&catid;=45&Itemid;=263⟨=en, https://www.plcnext-community.net/index.php?option=com_content&view;=article&id;=246&catid;=45&Itemid;=263⟨=en and https://www.plcnext-community.net/index.php?option=com_easydiscuss&view;=post&id;=877&Itemid;=221⟨=en, but apart from that they are a bit old, they hadn’t solved my problem. Both files, CsvParser.hpp and CsvParser.cpp, are attached (the program). Any help will be well received. Thanks! Best regards.
Hi Javier, I was working on a recent project where I wanted to use a 2D array (or an array of arrays, if you like) as a GDS variable, but I couldn’t make it work. It is possible to have an array of structs, and struct elements can be arrays, so I ended up having an array of structs, and each struct had one element (the other array). So your solution might be something like:
struct strSingleData
{
int16 iModbusType; // E_MODE
uint16 uiSlaveNo; // E_ADDRESS
int16 iFc; // E_FUNCTION
uint16 uiAddress; // E_BASE_REGISTER
int16 iQtyRegs; // E_NUM_OF_REGISTERS
int16 iOpcUaIndex; // E_OPCUA_INDEX
};
struct strNetwork
{
strSingleData arrNetwork[500];
};
//#port
//#attributes(Output|Opc|Proficloud)
strNetwork arrPlant[4];
(this compiles but I’m not 100% sure that it created the GDS port properly - if not, I can check this tomorrow). This use of structs turns out not to be so bad, because you can create another struct element in strNetwork alongside the arrNetwork element - a uint that represents the number of valid elements in the array. This helps the consumer of the array to only process the actual number of useful elements in the array, which can save time if some elements of arrPlant have significantly less than 500 useful elements in the arrNetwork array. Hope this helps! Martin.
Hi Martin! I tried it and it works for me. At least, what I could try for the moment, that is to create the library, imported in PLCnext Engineer and see that I have a port called “arrPlant”. Now, I only need to check that this type is recognized as compatible with the corresponding IEC61131 type. I’ll tell you the result. Thanks!
Great! I think you can add the port variable from the C++ program instance directly to the Watch window, and then expand it to check that the structure of the variable is what you expect. If you have trouble matching the C++ port variable with IEC types, let me know - basically, you should map the C++ struct types to IEC STRUCT types, and C++ arrays to IEC ARRAY types, etc. Martin.
Great idea! I did it, I added the C++ ports and the corresponding IEC61131 ports to the Watch Window, but… I have no good news. This is my code now:
struct strSingleData {
int16 iModbusType; // E_MODE
uint16 uiSlaveNo; // E_ADDRESS
int16 iFc; // E_FUNCTION
uint16 uiAddress; // E_BASE_REGISTER
int16 iQtyRegs; // E_NUM_OF_REGISTERS
int16 iOpcUaIndex; // E_OPCUA_INDEX
};
struct arrayNetwork {
uint16 length = 0;
strSingleData arrayNetwork[500];
};
//#port
//#attributes(Output|Opc|Proficloud)
//#name(strSingleData)
strSingleData singleDatas;
//#port
//#attributes(Output|Opc|Proficloud)
//#name(arraySingleData)
strSingleData arraySingleData[500];
//#port
//#attributes(Output|Opc|Proficloud)
//#name(arrayNetwork)
arrayNetwork arrayNetworks;
//#port
//#attributes(Output|Opc|Proficloud)
//#name(arrPlant)
arrayNetwork arrPlant[4];
The first three ports are only for testing purpose, but it let me saw an unexpected behaviour. A took a screenshot of the ports state and it structure
As you can see, only the structure (strSingleData) and a explicit array os this structure (strSingleData arraySingleData[500]) matched with IEC61131 types. However, the struct that contains the array of structs (arrayNetwork) and an array of that type (the one that I want, arrayNetwork arrPlant[4]) doesn’t match with the corresponding IEC61131 types. As you can see in the second picture, really >data is compatible. My solution for the moment will be make not an 2D array of structures, but 4 different arrays of structures (but as you can imagine, this isn’t very elegant). If I find something else, I’ll keep reporting. Thanks!
Hi Javi, I probably wasn’t as clear as I could have been. Here is what works for me:
* C++ port definition:
struct strSingleData
{
int16 iModbusType; // E_MODE
uint16 uiSlaveNo; // E_ADDRESS
int16 iFc; // E_FUNCTION
uint16 uiAddress; // E_BASE_REGISTER
int16 iQtyRegs; // E_NUM_OF_REGISTERS
int16 iOpcUaIndex; // E_OPCUA_INDEX
};
struct strNetwork
{
strSingleData arrNetwork[500];
};
//#port
//#attributes(Output|Opc|Proficloud)
strNetwork arrPlant[4];
* PLCnext Engineer data type definitions:
TYPE
> strSingleData : STRUCT
> iModbusType : INT;
> uiSlaveNo : UINT;
> iFc : INT;
> uiAddress : UINT;
> iQtyRegs : INT;
> iOpcUaIndex : INT;
> END_STRUCT
> END_TYPE
>
> TYPE
> strNetwork : STRUCT
> arrNetwork : ARRAY[0..499] OF strSingleData;
> END_STRUCT
> END_TYPE
>
> TYPE
> arrPlant : ARRAY[0..3] OF strNetwork;
> END_TYPE
… then create an IN port variable of type “arrPlant”. You will then be able to connect the IN port variable in the IEC program, to the OUT port variable from the C++ program. One trick is that PLCnext Engineer will not match port variables unless the STRUCT members have the same name (not just the same data type) in the IN and OUT ports. Hope this helps. Martin.
Hi, Finally, it works. Using the trick that you mentioned (the STRUCT members have the same name in C++ and PLCnex Engineer), ports are compatibles. Thank you for your time! Best regards
All, There is a cleaner way to do this that I just discovered. See below example. struct Inputs { boolean boolTest; float32 realTest; uint16 intTest; }; ----------------------------------- //#port //#attributes(Input) Inputs arrInputs[200];