MarshalAsAttribute массив строк - PullRequest
2 голосов
/ 04 ноября 2011

Я пытаюсь прочитать структуру тревоги из ПЛК Beckhoff в класс c #. Сначала я должен создать точно такую ​​же структуру в c #, и сейчас она выглядит так:

[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;
    }

Что вызывает у меня проблемы, это поле "instancePath". Когда поле является строкой, я могу использовать атрибут «UnmanagedType.ByValTStr» с SizeConst, а когда это массив «UnmanagedType.ByValArray», но когда я хочу использовать строку [], я не знаю, что делать.

Я пытался создать новый класс:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
    public class InstancePathDefinition
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
        public string instancePath;
    }

И используется в моем классе сигнализации:

[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;
    } 

Но когда я использую Marshal.SizeOf в моем классе Alarm, он дает мне размер или 147 байтов вместо 189 байтов, как я и ожидал.

EDIT: Я думаю, что причина разницы в размере заключается в том, что инициализируется только массив, а класс InstancePathDefinition - нет.

Я попытался изменить его с класса на структуру, и теперь размеры совпадают.

Мне все еще кажется странным, что я не могу объединить UnmanagedType.ByValArray и UnmanagedType.ByValTStr как подтип с другим SizeConst.

Далее мне нужно будет создать массив класса тревоги, и это снова вызовет у меня ту же проблему.

1 Ответ

2 голосов
/ 04 ноября 2011

Сделать массив структур вместо массива объектов класса.

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

Marshal.SizeOf () вернул 189, когда я попробовал.

...