Search code examples
c#arraysstringmarshallingtwincat

Beckhoff C# Reading array of string from PLC


I want to ask about reading string array from PLC Beckhoff.

I have some methods for reading Int16 - it works correctly

public Int16[] ReadArrFromPLC_Int16(string Mnemonic, int ArrLength)
{
    Int16[] TempVariable = null;

    try
    {
        ITcAdsSymbol itc = PLC3.adsClient.ReadSymbolInfo(Mnemonic);
        long indexGroup = itc.IndexGroup; ;
        long indexOffset = itc.IndexOffset;

        int[] args = { ArrLength }; 
        TempVariable = (Int16[])PLC3.adsClient.ReadAny(indexGroup, indexOffset, typeof(Int16[]) , args);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, Mnemonic);
    }
    return TempVariable;
}

but if I want to read array of string I get some exception: "Unable to marshal type. Parameter Name: type" in bold place: ...adsClient.ReadAny(indexGroup, indexOffset, typeof(string[]), args);

public string[] ReadArrFromPLC_String(string Mnemonic, int ArrLength)
{
    string[] TempVariable = null;

    try
    {
        ITcAdsSymbol itc = PLC3.adsClient.ReadSymbolInfo(Mnemonic);
        long indexGroup = itc.IndexGroup; ;
        long indexOffset = itc.IndexOffset;

        int[] args = { ArrLength };
        TempVariable = (string[])PLC3.adsClient.ReadAny(indexGroup, indexOffset, typeof(string[]), args);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, Mnemonic);
    }
    return TempVariable;
}

I can read the array in loop but it take long time.

I found similar topic: MarshalAsAttribute array of strings but I don't know does it help me? and I don't know how I can use it in my case.


Solution

  • Thank you Hans Passant for the tip.

    Below I show method - it works correctly, but I had to use loop in order to rewrite text from struct to string[].

    Is could be something to add?

        [StructLayout(LayoutKind.Sequential)]
        public struct MyString
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] 
            //SizeConst = 21 because in my PLC I declared 
            //"prg : ARRAY[0..200] OF STRING[20];" 
            //(0 to 20 = 21 characters)
            public string Str;
        }
        public string[] ReadArrFromPLC_String(string Mnemonic, int ArrLength)
        {
            MyString[] StrArrFromPLC = null;
            try
            {
                ITcAdsSymbol itc = PLC3.adsClient.ReadSymbolInfo(Mnemonic);
                long indexGroup = itc.IndexGroup; ;
                long indexOffset = itc.IndexOffset;
                int[] args = { ArrLength };
                StrArrFromPLC = (MyString[])PLC3.adsClient.ReadAny(indexGroup, indexOffset, typeof(MyString[]), args);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Mnemonic);
            }
            string[] TempVariable = new string[StrArrFromPLC.Length];
    
            for(int i = 0; i < StrArrFromPLC.Length; i++)
            {
                TempVariable[i] = StrArrFromPLC[i].Str;
            }
            return TempVariable;
        }