这个是我C#结构体
//结构体序列化   
[System.Serializable]   
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi,Pack = 4)]
public struct LoginError   
{
public uint id;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string psw;
public uint num;
}
这个是C++结构体
struct
{
DWORD ID;
CHAR PSW[32];
DWORD NUM;
}
C++往C#端发送,这个是转换的函数:
//字节数组转结构体
public static object BytesToStruct(byte[] bytes,   Type   strcutType)
 {
//得到结构体的大小
int size = Marshal.SizeOf(strcutType);
byte[] newBytes = new byte[size];
int length = bytes.Length>size?size:bytes.Length;
Array.Copy(bytes,newBytes,length);
//分配结构体大小的内存空间
IntPtr buffer = Marshal.AllocHGlobal(length);
//将byte数组拷到分配好的内存空间
Marshal.Copy(newBytes,0,buffer,length);
//将内存空间转换为目标结构体
object structObj = Marshal.PtrToStructure(buffer,strcutType);
Marshal.FreeHGlobal(buffer);
//释放内存空间
return structObj;
}
请问:
1、为什么我取出来的psw始终是null,如果我换成char[],上面也写成UnmanagedType.ByValArray,依然是{'0','0'......},或者我再用byte[],里面的值还是{0,0,0......}
2、C++里面编码好像是gb2312,我的开发环境是MonoDevelop+Mac OS下面的,如果上面能取出值那我还需要再转码么?(如果我拷贝一串字节数组,然后nickName = Encoding.GetEncoding("gb2312").GetString(userNameBytes);是可以得到正确的中文的)C#C++socket

解决方案 »

  1.   

    Pack = 4 这个可能最好改成Pack=1,除非你确定对方是按4字节对齐的。
    结构里有整数,你确定一下Mac OS下的字节序,不过两端都在同一平台下也无所谓
      

  2.   

    我又测试了下,byte[]貌似能取到,char[]还是不行,另外字节对齐服务器用的是默认的,那就应该是4字节对齐。我用Actionscript测试了这条消息是4字节对齐无误!
      

  3.   

    结果不对啊,char数组一直取不到值。不过byte数组我又测试了下,psw是能取到的
      

  4.   

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string psw;
    这种方式就可以,gb2312的可以解析出来结果不对啊,char数组一直取不到值。不过byte数组我又测试了下,psw是能取到的
      

  5.   

    结果不对啊,char数组一直取不到值。不过byte数组我又测试了下,psw是能取到的我把psw字段改成byte[]就可以正确的取出来了,为啥char[]就是不行呢??
      

  6.   

    C#的char是两个字节的
    结果不对啊,char数组一直取不到值。不过byte数组我又测试了下,psw是能取到的我把psw字段改成byte[]就可以正确的取出来了,为啥char[]就是不行呢??
      

  7.   

    结果不对啊,char数组一直取不到值。不过byte数组我又测试了下,psw是能取到的我把psw字段改成byte[]就可以正确的取出来了,为啥char[]就是不行呢??不会吧,那么用string呢?也是双字节??
      

  8.   

    结果不对啊,char数组一直取不到值。不过byte数组我又测试了下,psw是能取到的我把psw字段改成byte[]就可以正确的取出来了,为啥char[]就是不行呢?? CharSet = CharSet.Ansi这行设置了也无效??
      

  9.   

    用string接收byte[](字符串编码的)时,是按照SizeConst-1或者遇到\0处理的。
    你把byte[]转为struct,用char[]对应byte[]倒是也行,也能接收。
    但是在你把Struct转为IntPtr时,就不一样了。Char[]的字段,指定了SizeConst,那么Char[]的长度和字节数都是SizeConst值,这在Char[]里只有ASCII码字符时也没问题,但是如果Char[]里有汉字时,就不对了。
      

  10.   

    额,,那再请问下,C#的结构体里面,往C++端我要发送一个变长的数组怎么办,如果不加[MarshalAs(UnmanagedType.ByValArray, SizeConst = 33)]这句的话Marshal.SizeOf取出来的数据长度是错误的。
      

  11.   

    那就不能直接struct和byte[]互相转了,你需要按照各个字段的长度分别处理
      

  12.   

    谢谢啊!!好纠结~~原先封装结构体直接丢给底层去做了,现在还得拎出来开放个函数。不安规范写的服务端真是蛋疼!还是大学时代玩的C#,现在弄unity3d又回来琢磨- -
      

  13.   

    c#的string不应该出现在结构体内。不然和c++那边是不一样的。
    用char数组。
      

  14.   

    结贴了,原因找到了,c#里面的char是2字节的,c++是1字节的,所以应该用byte[]