Как прочитать структуру, содержащую массив структур из TwinCat в C#
Используя TwinCAT 3 ADS.Net для чтения из ПЛК, я пытаюсь прочитать структуру, содержащую массив структур, но команда ReadAny дает сбой с исключением "Unable to marshal type".
Хотя чтение массива структур работает нормально.
public object ReadAny(long indexGroup, long indexOffset, Type type, int[] args);
Замечание заголовка метода ReadAny гласит: "Если тип читаемого объекта является типом массива, число элементов для каждого измерения должно быть указано в параметре args".
Но что должно быть аргументом для структуры, содержащей массив структур? (Без "args" это тоже не получается.)
В настоящее время я работаю с.NET 4.7, VS 2013.
Есть ли вариант?
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public class WholeData
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public Station[] StationArray;
// Potentially more fields...
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public class Station
{
[MarshalAs(UnmanagedType.I1)]
public bool isPass;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 81)]
public string name;
// More fields...
}
// -- Main --
int[] args = { 5 };
// Works fine:
Station[] stationArray = (Station[])m_AdsClient.ReadAny(indexGroup, indexOffset, typeof(Station[]), args);
// Fail:
WholeData wholeData = (WholeData)m_AdsClient.ReadAny(indexGroup, indexOffset, typeof(WholeData), args);
// - OR -
WholeData wholeData = (WholeData)m_AdsClient.ReadAny(m_VarHandle, typeof(WholeData), args);
1 ответ
Решение
Я успешно протестировал следующий код:
код C#:
class Program
{
public static TcAdsClient client;
static void Main(string[] args)
{
// Create the ADS Client
using (client = new TcAdsClient())
{
// Establish Connection
client.Connect(new AmsAddress("10.1.2.95.1.1", 851));
int handle = client.CreateVariableHandle("PRG_AIS.stAds");
AdsClass ads = (AdsClass)client.ReadAny(handle, typeof(AdsClass));
ads.boolArr[0] = 1;
client.WriteAny(handle, ads);
Console.ReadLine();
}
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
class AdsClass
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public byte[] boolArr = new byte[10];
}
ST код:
TYPE AdsStruct :
STRUCT
bTestArray : ARRAY[0..9] OF BOOL;
END_STRUCT
END_TYPE
AdsStruct определяется как stAds в PRG_AIS.
ИЛИ, если у вас есть массив структур, измените код следующим образом:
код C#:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
class AdsClass
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public InnerStruct[] strArr = new InnerStruct[10];
}
struct InnerStruct
{
public byte bBoolTest;
public int nIntTest;
}
ST код:
TYPE AdsStruct :
STRUCT
stTestArray : ARRAY[0..9] OF InnerStruct;
END_STRUCT
END_TYPE
TYPE InnerStruct :
STRUCT
bBoolTest : BOOL;
nIntTest : DINT;
END_STRUCT
END_TYPE