我正在尝试将一个(相当陈旧的)C ++字符串消息映射到C#结构中,以便在某些新软件中进行处理。我遇到的问题是,当将C ++字符串消息映射到C#结构时,我正在丢失字符(可能是添加了\ 0)。
我需要处理的消息数据如下所示:“91000222201”
Where: "91" is one value
"0002" is the next value
"222" is the third value
"01" is the final value
我尝试的第一个结构布局是:
[StructLayout(LayoutKind.Sequential, Size = 11, CharSet = CharSet.Ansi), Serializable]
public struct HeaderPacketStruct
{
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 2)]
public string Value1;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 4)]
public string Value2;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 3)]
public string Value3;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 2)]
public string Value4;
}
它处理了字符串...但产生了以下值:
HeaderPacketStruct.Value1 = "9"
HeaderPacketStruct.Value1 = "000"
HeaderPacketStruct.Value1 = "22"
HeaderPacketStruct.Value1 = "0"
当我将每个字符串上的SizeConst碰到+1(以容纳“\ 0”)时,它开始丢弃字符:
HeaderPacketStruct.Value1 = "91"
HeaderPacketStruct.Value1 = "0022"
HeaderPacketStruct.Value1 = "01"
HeaderPacketStruct.Value1 = ""
看起来UnmanagedType.ByValTStr假设字符串末尾有一个“\ 0”。有没有办法解决这个问题?
顺便说一句,我能够在下面的struct中使用char []。但是,这个结构很难处理,因为每个值都是char []而不是字符串(在结构中)。对于所有处理,必须将char []重新映射到字符串中会非常痛苦。
StructLayout(LayoutKind.Sequential, Size = 11, CharSet = CharSet.Ansi), Serializable]
public struct HeaderPacketStruct
{
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2)]
public char[] Value1;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] Value2;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
public char[] Value3;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2)]
public char[] Value4;
}
答案 0 :(得分:2)
.NET中的Marshaling始终是错误的。字符串的编组是双虫!
我做了一些测试,ByValTStr
期望最后一个字符是'\0'
所以它读取它并忽略它(但问题是它读取它!)。你甚至不能使用LayoutKind.Explicit
作弊,因为它会因两个字段重叠的错误而爆炸。
你能做什么:
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2)]
private char[] value1;
public string Value1
{
get { return new string(this.value1); }
set { this.value1 = value.ToCharArray(); }
}
这是正常的。
答案 1 :(得分:0)
将FieldOffsetAttribute
添加到SizeConst时,只需添加正确的+1
即可。并且还注意到"91000222201"
字符串的大小等于12,而不是11.尝试这个:
[StructLayout(LayoutKind.Sequential, Size = 12, CharSet = CharSet.Ansi), Serializable]
public struct HeaderPacketStruct
{
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 3), FieldOffset(0)]
public string Value1;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 5), FieldOffset(2)]
public string Value2;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 4), FieldOffset(6)]
public string Value3;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 3), FieldOffset(9)]
public string Value4;
}