Im trying to read an alarm structure from a Beckhoff – PLC into a c# class.
First i have to make the exact same structure in c# and it currently looks like this:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class Alarm
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 81)]
public string text;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string objectName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public string[] instancePath = new string[6];
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string timeStamp;
public int priority;
[MarshalAs(UnmanagedType.I1)]
public bool acknowledge;
[MarshalAs(UnmanagedType.I1)]
public bool disabled;
[MarshalAs(UnmanagedType.I1)]
public bool alarmIn;
}
Whats causing me problems is the “instancePath” field.
When the field is a string i can use the “UnmanagedType.ByValTStr” attribute with SizeConst and when it’s an array “UnmanagedType.ByValArray” but when i want to use a string[] i don’t know what to do.
I’ve tried creating a new class:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class InstancePathDefinition
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string instancePath;
}
And used in my alarm class:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class Alarm
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 81)]
public string text;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string objectName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public InstancePathDefinition[] instancePath = new InstancePathDefinition[6];
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string timeStamp;
public int priority;
[MarshalAs(UnmanagedType.I1)]
public bool acknowledge;
[MarshalAs(UnmanagedType.I1)]
public bool disabled;
[MarshalAs(UnmanagedType.I1)]
public bool alarmIn;
}
But when I use Marshal.SizeOf on my Alarm-class it gives me a size or 147 bytes instead of 189 bytes as I would expect.
EDIT:
I think the reason for the difference in size is that only the array gets initiated and the class “InstancePathDefinition” doesn’t.
I tried changing it from a class to a struct and now the sizes match.
I still find it strange though that I can’t combine both UnmanagedType.ByValArray and UnmanagedType.ByValTStr as a sub type with different SizeConst.
Next I will need to create an array of the alarm class and that will get me into the same trouble again.
Make it an array of structures instead of an array of class objects.
Marshal.SizeOf() returned 189 when I tried it.