班级人数错误 [英] Error on size of class

查看:73
本文介绍了班级人数错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将字节数组转换为类或结构时遇到问题. 该类是这样的:

I have a problem with converting a byte array into a class or struct. The class is like this:

[Serializable()]
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public class General {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = Defines.CENTR_NAME_LENGTH + 1)] byte[] centralName;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = Defines.PROJECT_NAME_LENGTH + 1)] byte[] projectName;
    byte misc;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] byte[] accessCode2;
    byte transmActive;
    byte transmHour;
    byte transmMin;
    [MarshalAs(UnmanagedType.U1)] public int Cp;
    [MarshalAs(UnmanagedType.U1)] public int Rp;
    [MarshalAs(UnmanagedType.U1)] public int Lcd;
    [MarshalAs(UnmanagedType.U1)] public int Relais;
    [MarshalAs(UnmanagedType.U1)] public int Pr;
    [MarshalAs(UnmanagedType.U1)] public int Sc;
    byte rd;
    byte reserve1;
    [MarshalAs(UnmanagedType.U1)] public int LocalCentrId;
    [MarshalAs(UnmanagedType.U1)] public int PrinterSel;
    [MarshalAs(UnmanagedType.U1)] public int Slave1;
    [MarshalAs(UnmanagedType.U1)] public int Slave2;
    [MarshalAs(UnmanagedType.U1)] public int Slave3;
    [MarshalAs(UnmanagedType.U1)] public int Master;
    [MarshalAs(UnmanagedType.U1)] public int AlarmRepeat;
    [MarshalAs(UnmanagedType.U1)] public int FaultRepeat;
    [MarshalAs(UnmanagedType.U1)] public int ResetSil1;
    [MarshalAs(UnmanagedType.U1)] public int ResetSil2;
    [MarshalAs(UnmanagedType.U1)] public int EvacDelayed1;
    [MarshalAs(UnmanagedType.U1)] public int EvacDelayed2;
    [MarshalAs(UnmanagedType.U1)] public int Led1;
    [MarshalAs(UnmanagedType.U1)] public int Led2;
    [MarshalAs(UnmanagedType.U1)] public int GenControl;
    [MarshalAs(UnmanagedType.U1)] public int ExtraGenControl;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = Defines.MAX_NMB_SIL_CONTROL)] byte[] silenceControls ;
    byte autoResetFault;
    byte autoResetSC;
    [MarshalAs(UnmanagedType.U1)] public int InitEvacDelay;
    [MarshalAs(UnmanagedType.U1)] public int SilenceEvacOff;
    byte summerTime;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] byte[] accessCode1;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] byte[] btPinCode;

    public string CentralName { get { return Encoding.ASCII.GetString(centralName); } set { centralName = Encoding.ASCII.GetBytes(value); } }
    public string ProjectName { get { return Encoding.ASCII.GetString(projectName); } set { projectName = Encoding.ASCII.GetBytes(value); } }
    public bool BackBeep { 
        get { 
            return (misc & 0x01) != 0x00;
        }
        set {
            if (value) {
                misc |= 0x01;
            } else {
                misc ^= 0x01;
            }
        }
    }
    public bool StartStopEvac {
        get {
            return (misc & 0x02) != 0x00;
        }
        set {
            if (value) {
                misc |= 0x02;
            } else {
                misc ^= 0x02;
            }
        }
    }
    public bool GenBehEvacKey {
        get {
            return (misc & 0x04) != 0x00;
        }
        set {
            if (value) {
                misc |= 0x04;
            } else {
                misc ^= 0x04;
            }
        }
    }
    public bool GenBehEvacDet {
        get {
            return (misc & 0x08) != 0x00;
        }
        set {
            if (value) {
                misc |= 0x08;
            } else {
                misc ^= 0x08;
            }
        }
    }
    public bool EvacDelayed {
        get {
            return (misc & 0x10) != 0x00;
        }
        set {
            if (value) {
                misc |= 0x10;
            } else {
                misc ^= 0x10;
            }
        }
    }
    public bool SirService {
        get {
            return (misc & 0x20) != 0x00;
        }
        set {
            if (value) {
                misc |= 0x20;
            } else {
                misc ^= 0x20;
            }
        }
    }
    public bool ResetSilService {
        get {
            return (misc & 0x40) != 0x00;
        }
        set {
            if (value) {
                misc |= 0x40;
            } else {
                misc ^= 0x40;
            }
        }
    }
    public string AccessCode1 { get { return Encoding.ASCII.GetString(accessCode1); } set { accessCode1 = Encoding.ASCII.GetBytes(value); } }
    public string AccessCode2 { get { return Encoding.ASCII.GetString(accessCode2); } set { accessCode2 = Encoding.ASCII.GetBytes(value); } }
    public bool EvacDirect { get { return transmActive == 0x01; } set { transmActive = (Byte)(value ? 0x01 : 0x00); } }
    public TimeSpan EvacDirectTime { get { return new TimeSpan(transmHour, transmMin, 0); } set { transmHour = (Byte)value.Hours; transmMin = (Byte)value.Minutes; } }
    public bool Rd { get { return rd == 0x01; } set { rd = (value ? (Byte)0x01 : (Byte)0x00); } }
    public List<int> SilenceControl {
        get {
            List<int> retVal = new List<int>();
            if (silenceControls != null) {
                foreach (byte b in silenceControls) {
                    retVal.Add(b);
                }
            }
            return retVal;
        } 
        set {
            silenceControls = new byte[Defines.MAX_NMB_SIL_CONTROL];
            for (int t = 0; t < Defines.MAX_NMB_SIL_CONTROL && t < value.Count; ++t) {
                silenceControls[t] = (Byte)value[t];
            }
        }
    }
    public bool AutoResetFault { get { return autoResetFault == 0x01; } set { autoResetFault = (Byte)(value ? 0x01 : 0x00); } }
    public bool AutoResetPower { get { return autoResetSC == 0x01; } set { autoResetSC = (Byte)(value ? 0x01 : 0x00); } }
    public bool SummerTime { get { return summerTime == 0x01; } set { summerTime = (Byte)(value ? 0x01 : 0x00); } }
    public string BtPinCode { get { return Encoding.ASCII.GetString(btPinCode); } set { btPinCode = Encoding.ASCII.GetBytes(value); } }

    public General() {
        Console.WriteLine("Create General");
        SetDefault();
    }

    public void SetDefault() {
        CentralName = "MD2400";
        ProjectName = "Limotec";
        Cp = 1;
        Rp = 0;
        Lcd = 0;
        Relais = 1;
        Pr = 0;
        Sc = 1;
        Rd = true;
        BackBeep = false;
        AccessCode1 = "654321";
        AccessCode2 = "123456";
        EvacDirect = false;
        EvacDirectTime = new TimeSpan( 0, 0, 0 );
        BtPinCode = "1111111111111111";
        SummerTime = true;
        GenControl = 1;
        ExtraGenControl = 0;
        SilenceControl.Add( 3 );
        InitEvacDelay = 2;
        EvacDelayed = false;
        StartStopEvac = false;
        SirService = false;
        ResetSilService = false;
        GenBehEvacKey = true;
        GenBehEvacDet = true;
        Master = 32;
        Slave1 = 0;
        Slave2 = 0;
        Slave3 = 0;
        AlarmRepeat = 0;
        FaultRepeat = 0;
        ResetSil1 = 0;
        ResetSil2 = 0;
        Led1 = 0;
        Led2 = 0;
        EvacDelayed1 = 0;
        EvacDelayed2 = 0;
        LocalCentrId = 0;
        AutoResetFault = true;
        AutoResetPower = true;
    }

    [OnDeserialized()]
    internal void OnDeserialized(StreamingContext contect) {
        Config.Singleton.Log.Info( string.Format( "General loaded: {0} {1}", CentralName, ProjectName ) );
    }
}

当我执行Marshall.SizeOf(typeof(General))时,我收到ArgumentException.无法计算大小或偏移量.

When I do Marshall.SizeOf(typeof(General)) I get an ArgumentException. The size or offset cannot be calculated.

如果我在同一类中使用私有变量和公共属性,是否有问题?这些属性仅用于将变量转换成更有用的东西. (将字节数组转换为字符串)

Is there a problem if I use private variables and public properties in the same class? The properties are only for converting the variable in something more usefull. (Byte array into string)

如何解决它,以便可以使用Marshal.PtrToStructure将字节数组放入类中?

How can I solve it so that I can put a byte array into the class using Marshal.PtrToStructure ?

推荐答案

对我来说,它可以正常工作:我得到43,它与2 * 21 + 1一致.我已经检查了.NET 2.0、3.5和4.5(对于4.5我同时检查了x86和x64)-看起来还不错.

For me it just works: I get 43, which agrees with 2 * 21 + 1. I've checked .NET 2.0, 3.5 and 4.5 (and for 4.5 I checked both x86 and x64) - it just seems fine.

不,属性无关紧要:元帅代码仅查看字段.

No, properties don't matter: the marshal code is only looking at fields.

会发生什么是因为数据不匹配:

无法整理类型,因为嵌入式数组实例的长度与布局中声明的长度不匹配.

Type could not be marshaled because the length of an embedded array instance does not match the declared length in the layout.

您需要确保数组的长度正确-以下内容很难看,但是可以排序(不要设置超长字符串!):

You need to ensure the arrays are of the right length - the following is ugly, but works, sort-of (don't set an over-length string!):

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)]
byte[] centralName = new byte[21];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)]
byte[] projectName = new byte[21];
byte misc;

public string CentralName {
    get {
        int i = Array.IndexOf(centralName, (byte)0);
        if (i < 0) i = centralName.Length;
        return Encoding.ASCII.GetString(centralName, 0, i);
    }
    set {
        Array.Clear(centralName, 0, centralName.Length);
        Encoding.ASCII.GetBytes(value, 0, value.Length, centralName, 0);
    } }
public string ProjectName {
    get {
        int i = Array.IndexOf(projectName, (byte)0);
        if (i < 0) i = projectName.Length;
        return Encoding.ASCII.GetString(projectName, 0, i);
    }
    set {
        Array.Clear(projectName, 0, projectName.Length);
        Encoding.ASCII.GetBytes(value, 0, value.Length, projectName, 0);
    } }

示例:

unsafe static void Main()
{
    int i = Marshal.SizeOf(typeof(General));
    General obj = new General { CentralName = "abc", ProjectName = "def" },
            clone;
    byte[] b = new byte[i];
    fixed(byte* a = b)
    {
        IntPtr ptr= new IntPtr(a);
        Marshal.StructureToPtr(obj, ptr, false);
        clone = (General) Marshal.PtrToStructure(ptr, typeof(General));
    }
    Console.WriteLine(clone.CentralName); // abc
    Console.WriteLine(clone.ProjectName); // def
}

或:

unsafe static void Main()
{
    int i = Marshal.SizeOf(typeof(General));
    General obj = new General { CentralName = "abc", ProjectName = "def" },
            clone;
    byte* a = stackalloc byte[i];

    IntPtr ptr= new IntPtr(a);
    Marshal.StructureToPtr(obj, ptr, false);
    clone = (General) Marshal.PtrToStructure(ptr, typeof(General));

    Console.WriteLine(clone.CentralName); // abc
    Console.WriteLine(clone.ProjectName); // def
}

这篇关于班级人数错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆