[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct TPlayList { public int ActTime; public int Action; public int Speed; public int ListNum; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public TLabelContent[] Content;
public TPlayList(int count) { ActTime = 0; Action = 0; Speed = 0; ListNum = count; Content = new TLabelContent[5]; } } //下发节目单 [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct TPlayListInfo { public byte DevType; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public char[] DevCode; public int Page; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public TPlayList[] PlayList;
public TPlayListInfo(int count) { DevType = 1; DevCode = new char[10]; Page = 0; PlayList = new TPlayList[10]; } } 为什么加上[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]大小依然是77
public TPlayListMsg(int count)这个构造函数没用上?
你用的是默认的隐藏无参数构造函数实例化的结构体啊
而这个count你根本没有传入
msg.PlayListInfo.PlayList = new TPlayList[10];
for (int i = 0; i <= 9; i++)
{
msg.PlayListInfo.PlayList[i].Content = new TLabelContent[5]; for (int j = 0; j <= 4; j++)
msg.PlayListInfo.PlayList[i].Content[j].FileName = "aa".PadRight(255,'\0').ToCharArray();
} MessageBox.Show(Marshal.SizeOf(msg).ToString());
你应该TPlayListMsg msg = new TPlayListMsg(10);啊
为什么先用无参数的构造函数实例化,再到结构体里面去循环赋值?
这结构体真的是你自己写的吗,怎么感觉你自己都不会用的
知道为啥是固定的77了他是只算了
public TMsgHeadInfo MsgHead;
public TPlayListInfo PlayListInfo;这两个结构里面的基本类型的字段
然而里面的
public TLabelContent[] Content;
TPlayList[] PlayList 这个他实际只是取得 这个Content,PlayList的指针地址的长度也就是8
而你要取的是每个Content与PlayList实际New 后每个项的长度之和这个搞不了
其实就是要把所有的数据放到这个结构体里,通过SOCKET发出去,有啥其他解决方法吗?
其实就是要把所有的数据放到这个结构体里,通过SOCKET发出去,有啥其他解决方法吗?
那你结构体里应该放值类型,而不要放引用类型的东西
否则在序列化的时候,依然还是不会把引用类型的东西一起序列化
我们一般是这么处理的
Buffer.WriteInt(数组个数)
[
for(int i=0;i<数组个数++)
Buffer.WriteBytes(结构体数据[i]);
]return Buffer.ToArray();
然后接收先
int x=ReadInt();先取数量
for(int i=0;i<x)
{
结构体Buffer=ReadBuffer();
}
其实就是要把所有的数据放到这个结构体里,通过SOCKET发出去,有啥其他解决方法吗?
那你结构体里应该放值类型,而不要放引用类型的东西
否则在序列化的时候,依然还是不会把引用类型的东西一起序列化
不过delphi,vc都是可以的
而且VC里结构体数组本身就是连续存放的,直接指向内存首地址,不存在什么序列化的问题
2+2+1+6+1+6+4+32+(这是TMsgHeadInfo的长度)
1+10+4+8(这是TPlayListInfo的长度)
正好是77,一点没错。从你的发言中,可以看出你根本不会VC++,所以写的C#代码也是半桶水。
在VC++里面,数组是定长的,就不存在可变长度数组,定义的时候必须指定长度,但是你看你定义的TPlayListInfo中,“public TPlayList[] PlayList;”就没指定长度,你希望在运行时动态给长度,这种做法在C++里面你试试,你能定义一个运行时动态改变长度的结构体吗?除非用指针,否则变长数组肯定不行。因此这里在计算时,系统用了Inptr的长度,也就是8字节。
VC++我不会,我并没有说VC中数组是可变的,另外我也没说要动态的给长度吧,你从哪看出我说这话了,C#我也是初学者,到不了半桶水,麻烦高手您,解答一下我的问题应该如何解决吧
事实上,在C#里面,除了byte[]是连续分配的内存地址外,其他结构体数组都是相当于VC里面的结构体指针,只是通过MarshalAs这个特性告诉Marshal类,在使用Marshal.SizeOf时,通过特性来获取结构体长度,并可以利用Marshal类的字节到结构体的拷贝函数,自动根据你的每个属性的MarshalAs特性来完成结构体拷贝。
struct TPlayList
{
public int ActTime;
public int Action;
public int Speed;
public int ListNum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public TLabelContent[] Content;
public TPlayList(int count)
{
ActTime = 0;
Action = 0;
Speed = 0;
ListNum = count;
Content = new TLabelContent[5];
}
}
//下发节目单
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct TPlayListInfo
{
public byte DevType;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public char[] DevCode;
public int Page;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public TPlayList[] PlayList;
public TPlayListInfo(int count)
{
DevType = 1;
DevCode = new char[10];
Page = 0;
PlayList = new TPlayList[10];
}
}
为什么加上[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]大小依然是77