4

我正在尝试将(相当古老的)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”。有没有办法解决?

顺便说一句,我能够在下面的结构中使用 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;
}
4

2 回答 2

5

.NET 中的编组总是有问题的。字符串的编组是双重错误!

我已经进行了一些测试,并且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(); }
}

这可以正常工作。

于 2013-09-14T06:59:36.627 回答
-2

添加到 SizeConstFieldOffsetAttribute时,只需在 case 中添加正确的 s。+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;
}
于 2013-09-14T07:14:01.060 回答