MarshalAsAttribute array of strings

匿名 (未验证) 提交于 2019-12-03 09:05:37

问题:

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.

回答1:

Make it an array of structures instead of an array of class objects.

[StructLayout(LayoutKind.Sequential)] public struct InstancePathDefinition {     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]     public string path; } 

Marshal.SizeOf() returned 189 when I tried it.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!