C#中字符串的结构映射问题

时间:2013-09-14 06:29:03

标签: c# string struct structure marshalling

我正在尝试将一个(相当陈旧的)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;
}

2 个答案:

答案 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;
}