简体   繁体   English

C#封送非ASCII字符串?

[英]C# marshaling non-ASCII string?

I'm developing an online game which has to trade packets with a C++ server. 我正在开发一个在线游戏,该游戏必须与C ++服务器交换数据包。 I'm doing it using the Unity 5 engine. 我正在使用Unity 5引擎进行操作。 My life was getting hard when I started to write the packet structures in the C# code using Marshaling. 当我开始使用Marshaling用C#代码编写数据包结构时,我的生活变得越来越艰难。 Unity have serious bugs here, but ok for all of the Unity related bugs I'm used to implement any sort of workaround, but this bug I'm facing right now I think it could be some Marshal's limitation. Unity在这里有严重的错误,但是对于我用来实现任何变通办法的所有与Unity相关的错误都可以,但是我现在面临的这个错误我认为这可能是元帅的局限性。

I have this C# struct: 我有这个C#结构:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MSG_SendNotice : IGamePacket
{
    public const PacketFlag Opcode = (PacketFlag)1 | PacketFlag.Game2Client;

    private PacketHeader m_Header;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 96)]
    public string Text;

    public PacketHeader Header { get { return m_Header; } }
}

It should works fine when calling Marshal.PtrToStructure. 调用Marshal.PtrToStructure时,它应该可以正常工作。 The problem is when some non-ascii character is sent on Text. 问题是在文本上发送了一些非ASCII字符时。 The Marshal fails the conversion and assign null to Text. 元帅转换失败并为Text分配null。 If I manually change this non-ascii character to any ascii character before converting the packet buffer the marshal works. 如果我在转换数据包缓冲区之前手动将此非ascii字符更改为任何ascii字符,则封送工作。 The point is that I canno't format all the packets server-side to avoid send these non-ascii characters, I actually need them to display the correct string. 关键是我无法在服务器端格式化所有数据包以避免发送这些非ASCII字符,我实际上需要它们显示正确的字符串。 Is there a way to set the encoding of this marshaled string (Text) in its definition? 有没有办法在其定义中设置此封送处理的字符串(文本)的编码?

A ny ideas are appreciated, thanks very much. 感谢您的想法,非常感谢。

I would encode/decode the string manually: 我会手动编码/解码字符串:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)]
public byte[] m_Text;

public string Text
{
    get
    {
        return m_Text != null ? Encoding.UTF8.GetString(m_Text).TrimEnd('\0') : string.Empty;
    }

    set
    {
        m_Text = Encoding.UTF8.GetBytes(value ?? string.Empty);
        Array.Resize(ref m_Text, 96);
        m_Text[95] = 0;
    }
}

Note that on set I'm manually adding a final 0 terminator ( m_Text[95] = 0 ) to be sure the string will be a correctly-terminated C string. 请注意,在设置时,我手动添加了最后一个0终止符( m_Text[95] = 0 ),以确保该字符串将是正确终止的C字符串。

I've done a test: it works even in the case that m_Text is null. 我已经做了测试:即使m_Text为null,它也可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM