结构体:
 public struct tagCITIZEN_QUERY
 {
     public int cState;     
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
     public char[] czID;             //长度为20      
 }
转换方法:
public byte[] StructToBytes<T>(T obj)
{
     int size = Marshal.SizeOf(obj);
     byte[] bytes = new byte[1024];
     IntPtr arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
     Marshal.StructureToPtr(obj, arrPtr, true);      //#1异常处
     return bytes;
}
调用代码:
tagCITIZEN_QUERY query = new Connection.tagCITIZEN_QUERY();
query.cState = 0;
query.czID = ("12345678901234567890").ToCharArray();byte[] buffer = StructToBytes<tagCITIZEN_QUERY>(query);在#1处出现异常:“未能封送类型,因为嵌入数组实例的长度与布局中声明的长度不匹配”。请问这是什么原因?我用另一个结构体
public struct tagMSG_HEAD
{
     public char msgtype;         
      public short len;        
}
时这段代码没有问题,是不是第一个结构体内有 CHAR[] 的原因?

解决方案 »

  1.   

    use this struct public enum CmdType
        {
            LOGIN = 0,
            EXIT,
            MSG,
            CLOSE,
            DEFAULT
        }    public struct TcpPack
        {
            public Byte[] _data;        public CmdType _command;//包类别,枚举,长度2
            private UInt16 _length;//记录数据长度 ,2
            private UInt16 _ckSum;//校检,长度2
            private UInt16 _sequence;//顺序号 长度2        /// <summary>
            /// dataLength 数据部分长度
            /// </summary>
            /// <param name="dataLength"></param>
            public TcpPack(UInt16 dataLength)
            {
                _command = CmdType.DEFAULT;
                _ckSum = 0;
                _data = new byte[dataLength];
                _length = (UInt16)_data.Length;
                _sequence = 0;
            }        /// <summary>
            /// 基本构造函数
            /// </summary>
            /// <param name="command"></param>
            /// <param name="checkSum"></param>
            /// <param name="data"></param>
            public TcpPack(CmdType command, UInt16 checkSum, Byte[] data)
            {
                _command = command;
                _ckSum = checkSum;
                _data = new byte[data.Length];
                _data = data;
                _length = (UInt16)_data.Length;
                _sequence = 0;
            }        /// <summary>
            /// Sequence 顺序号
            /// </summary>
            /// <param name="command"></param>
            /// <param name="checkSum"></param>
            /// <param name="data"></param>
            /// <param name="Sequence"></param>
            public TcpPack(CmdType command, UInt16 checkSum, Byte[] data, UInt16 Sequence)
            {
                _command = command;
                _ckSum = checkSum;
                _data = new byte[data.Length];
                _data = data;
                _length = (UInt16)_data.Length;
                _sequence = Sequence;
            }
            /// <summary>
            /// 序列化包体
            /// </summary>
            /// <param name="buffer"></param>
            /// <returns></returns>
            public int ConvertToByte(Byte[] buffer)
            {
                Byte[] b_command = BitConverter.GetBytes((UInt16)_command);
                Byte[] b_ckSum = BitConverter.GetBytes(_ckSum);
                Byte[] b_length = BitConverter.GetBytes(_length);
                Byte[] b_sequence = BitConverter.GetBytes(_sequence);
                int index;
                index = 0;            Array.Copy(b_command, 0, buffer, index, b_command.Length);
                index += b_command.Length;            Array.Copy(b_ckSum, 0, buffer, index, b_ckSum.Length);
                index += b_ckSum.Length;            Array.Copy(b_length, 0, buffer, index, b_length.Length);
                index += b_length.Length; ;            Array.Copy(b_sequence, 0, buffer, index, b_sequence.Length);
                index += b_sequence.Length;            Array.Copy(_data, 0, buffer, index, _data.Length);
                index += _data.Length;
                return index;
            }        /// <summary>
            /// 反序列化包头
            /// </summary>
            /// <param name="buffer"></param>
            /// <returns></returns>
            public TcpPack ConvertToStruct(Byte[] buffer)
            {
                _command = (CmdType)BitConverter.ToUInt16(buffer, 0);
                _ckSum = BitConverter.ToUInt16(buffer, 2);
                _length = BitConverter.ToUInt16(buffer, 4);
                _sequence = BitConverter.ToUInt16(buffer, 6);
                _data = new Byte[_length];
                return this;
            }        public UInt16 CheckSum
            {
                get
                {
                    return _ckSum;
                }
                set
                {
                    _ckSum = value;            }
            }        public static UInt16 HeadLength
            {
                get
                {
                    return 8;
                }
            }        public static UInt16 MaxDataLength
            {
                get
                {
                    return 1024;
                }
            }
            public UInt16 GetSequence
            {
                get
                {
                    return _sequence;
                }
            }        public UInt16 GetDataLength
            {
                get
                {
                    return _length;
                }
            }
        }
      

  2.   

    2楼的方法看了,我现在想写一个通用的转换,因为后续的结构体还有很多,我认为是CHAR[] 那里的问题,不知道有没有人遇到过
      

  3.   

    其实全部可以用byte来操作的.
      

  4.   

      结构体: 
    [Serializable]//标记为可序列化
    public struct tagCITIZEN_QUERY 

        public int cState;     
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] 
        public char[] czID;            //长度为20      

      public byte[] StructToBytes<T>(T obj)
            {
                BinaryFormatter formatter = new BinaryFormatter();
                MemoryStream memStream = new MemoryStream();
                formatter.Serialize(memStream, obj);
                byte[] bytes = memStream.GetBuffer();
                memStream.Close();
                return bytes;
            } 
      

  5.   

     char[] czID;       是长度20所以你要这样做

    byte czIDbak= new byte[20];for(int i =0;i<20;i++){
    czIDbak[i]=0x00;
    }然后你再复制数组
    Array.Copy(........这样才可以转换数组
    StructToBytes<T>(T obj)....这样才可以发送
    因为我现在的项目中做的和你说类似的事
      

  6.   


    没有出现问题? 难道是我系统VISTA的原因?
      

  7.   

    query.czID = ("12345678901234567890").ToCharArray(); byte[] buffer = StructToBytes <tagCITIZEN_QUERY>(query); 
    记住这里不能直接转,你要保证数组大小一致,("12345678901234567890")字符串转byte[]不够长的要用空白填充
    这样就不得数组越界,这是问题的所在
      

  8.   

    Array.Copy 是在哪里进行呢?
      

  9.   

    最好是每个类型自己提供转到byte[]的方法,然后就可以定义一个共同的接口public interface IConvertibleToByteArray
    {
        byte[] ToBytes();
    }如果真的想用一个静态方法来把所有的可能的类型都转化成byte[],估计要用点反射。
      

  10.   

    是否存在Char[]的结构体无法通过 Marshal.StructureToPtr(obj, arrPtr, true) 直接转呢? 
      

  11.   

    是否因为CHAR是16位的,BYTE是8位的?
      

  12.   

    晕倒,查到问题所在了
    char[] czID 长度定成20后,实际数据长度不足20,又没有自动补位.....也谢谢各位~~~
    结贴了~~