【问题标题】:Trying to get the c# equivalent of a c++ class试图获得与 c++ 类等效的 c#
【发布时间】:2018-11-26 07:38:12
【问题描述】:

我正在尝试获得与 C++ 类等效的 C#,我对 C++ 有非常非常基础的知识,所以如果这真的可能的话,我想知道。我尝试了一些东西,但我被卡住了。因此,如果您可以帮助我将这个 c++ 类“解析”为 c#,并解释一下您是如何做到的,或者提供一些可以帮助我的链接。 (或者给我一个在我的 c# 项目中使用这个 c++ 类的提示(如果可能因为托管/非托管代码等,idk。)

C++ 类:

class GameString
{
public:
    GameString (GameString const&) = delete;
    GameString& operator=(GameString const&) = delete;

    GameString (const std::string &str)
        : _buf (8)
    {
        append (str);
        setHeader (1, length ());
    }

    GameString& operator+=(const std::string &str)
    {
        append (str);
        setHeader (1, length ());

        return *this;
    }

    std::size_t length ()
    {
        return _buf.size () - 8;
    }
    char *str ()
    {
        return reinterpret_cast<char*>(_buf.data () + 8);
    }

private:
    std::vector<unsigned char> _buf;

    void append (const std::string &str)
    {
        for (auto &c : str)
        {
            _buf.push_back (c);
        }
    }

    void setHeader (std::size_t ref, std::size_t len)
    {
        memcpy (&_buf[0], &ref, 4);
        memcpy (&_buf[4], &len, 4);
    }
};

C#类:

class GameString
{
    private List<char> _buf = new List<char>(8);

    public GameString(string str)
    {
        Append(str);
        SetHeader(1, Length());
    }

    private void Append(string str)
    {
        foreach (char c in str)
        {
            _buf.Add(c);
        }
    }

    public int Length()
    {
        return _buf.Count - 8;
    }

    public string Str()
    {
        // return new String(_buf.ToArray());
    }

    private void SetHeader(int rf, int length)
    {
        // memcpy(&_buf[0], &ref, 4);
        // memcpy(&_buf[4], &len, 4);
    }
}

感谢您的帮助

【问题讨论】:

  • 如果你能从 c# 类中详细说明你需要的行为,这可能会有所帮助。
  • 看起来你基本上是在问应该如何实现Str()。对吗?
  • 是的,这就是我正在寻找的,我试图从 str() 方法以及如何在 C# 中创建 SetHeader() 方法获得相同的结果,因为它可能会更改值我不能忽视它。

标签: c# c++ visual-c++


【解决方案1】:
public class GameString
{
    private MemoryStream buf;

    public GameString(string str)
    {
        buf = new MemoryStream();

        // 8 empty bytes at the beginning
        buf.SetLength(8);
        buf.Position = 8;

        Append(str);
    }

    // Different from C++ implementation. This one is public
    // and updates the SetHeader
    public void Append(string str)
    {
        byte[] utf8 = Encoding.UTF8.GetBytes(str);
        buf.Write(utf8, 0, utf8.Length);
        SetHeader(1, Length);
    }

    public static GameString operator +(GameString gs, string str)
    {
        gs.Append(str);
        return gs;
    }

    // This one is a property instead of being a method
    public int Length { get => (int)buf.Length - 8; }

    // The char *str ()
    public override string ToString()
    {
        return Encoding.UTF8.GetString(buf.GetBuffer(), 8, (int)buf.Length - 8);
    }

    // This one was missing in the C++ implementation. Returns the internal buffer.
    // trimmed to the correct length. Note that it creates a copy!
    public byte[] ToByteArray()
    {
        return buf.ToArray();
    }

    private void SetHeader(int @ref, int len)
    {
        // This could be optimized. Sadly the GetBytes create new
        // arrays as the return value, instead of writing to a 
        // preexisting array.
        byte[] temp = BitConverter.GetBytes(@ref);
        Buffer.BlockCopy(temp, 0, buf.GetBuffer(), 0, temp.Length);

        temp = BitConverter.GetBytes(len);
        Buffer.BlockCopy(temp, 0, buf.GetBuffer(), 4, temp.Length);
    }
}

然后:

var gs = new GameString("Foo");
gs.Append("Bar");
gs.Append("Baz");
gs += "Hello";
gs += "World";
string str = gs.ToString();
byte[] bytes = gs.ToByteArray();

我对 C++ 代码进行了一些更改,并在 C# 代码中添加了注释。

我使用的是MemoryStream,而不是List&lt;&gt;StringBuilderchar 在 C# 中是 2 个字节,而在 C 中是 1 个字节,所以在 C# 中你应该使用 byte,而不是 char

【讨论】:

    【解决方案2】:

    由于标题似乎是固定值 1 和长度,除非我遗漏了什么

    您可以轻松地使用 stringstring.Length();

    // instantiate
    string gameString = "sadasd";
    
    // get length
    var len = gameString.Length();
    
    // append
    gameString += "sdfsfsdfdsf";
    
    // get length again
    var newLen = gameString.Length();
    

    【讨论】:

    • 谢谢,但事情没那么简单。我正在尝试将数据包发送到游戏服务器,但数据包中的字符串不能是简单的字符串,这就是创建此类的原因,用于将经典字符串“转换”为正确的数据包字符串。例如:GameString gamestr("mypacket") 的 str() 方法返回:mypacketÍÍýý 当我将此数据包发送到服务器时,它可以工作,但是当我只发送“mypacket”时,他就无法工作。希望你能理解,我的英语很糟糕:/
    • 那么服务器想要什么,只是标准的 ascii 字节?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    • 2010-12-04
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多