【问题标题】:Convert C++ struct to C# struct将 C++ 结构体转换为 C# 结构体
【发布时间】:2015-02-16 12:52:18
【问题描述】:

我需要将结构转换为字节,以便我可以通过网络发送或接收它。

假设结构如下所示:

struct Info
{
    unsigned int Age;
    char Name[];
};

我在 C# sharp 中有等效的结构,即:

[StructLayout(LayoutKind.Sequential)]
public struct Info
{
    public uint Age;
    public string Name;
};

要将 C# 结构转换为字节,我使用以下方法:

    public Byte[] GetBytes(Info info)
    {
        int size = Marshal.SizeOf(info);
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.StructureToPtr(info, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);

        return arr;
    }

为了将接收到的字节转换为 C++ 结构,我使用这种方法:

Info GetInfo(const char* bytes)
{
    Info info;
    memcpy(&info, bytes, sizeof(info));

    return info;
}

我的问题是结构的 Age 字段转换得很好,但 Name 字段从来不是已发送的内容。

更新

我可以使用下面的代码轻松地将字符串转换为字节,并将其从 c# 客户端应用程序发送到 c++ 服务器应用程序。

        byte[] buffer = Encoding.UTF8.GetBytes(text + "\0");

所以我决定将 C# 结构更改如下:

[StructLayout(LayoutKind.Sequential)]
public struct Info
{
    public uint Age;
    public byte[] Name;
};

但在这种情况下,GetBytes() 方法会崩溃。

【问题讨论】:

  • 您能否提供一些信息,说明您为什么需要一个结构,以及为什么需要将其转换为字节?
  • 有点难;你能看到“在线”传输的内容吗?
  • 如果年龄有效但名称无效,您可能正在处理某种字符集编码不匹配问题。
  • C++ 代码没有使用CMsg。我糊涂了。在任何情况下,我相信 C++ 中结构的大小是由实现定义的(特别是因为您使用的是“C struct hack”)。名称的长度可变。在 C# 中,string 成员只是对在堆上分配的实际字符串的引用,因此除了复制结构的字节之外,您还需要做更多的工作。
  • 转换整个结构永远不会正确。您必须逐场进行。在 c# 方面,您最有可能获得字符串大小和字符串内容,而在 C++ 方面,没有长度。另外,在 C# 端字符串是 Unicode,每个字符 16 位,而在 C++ 端它们只是字符。我建议使用像kentonv.github.io/capnproto 这样的罐装解决方案

标签: c# c++ struct converter


【解决方案1】:
  1. 您的 C++ 结构使用灵活的数组成员作为最后一个元素,这是从 C99 借用的扩展:

    本质上,它意味着一个未知长度的数组结束它。
    由于长度未知,编译器将在询问结构大小时假定 0。
    我有点怀疑这就是你想要的。

  2. 您的 C# 结构有一个 string-member,它不是值类型。

    像你一样将托管指针复制到它是非常荒谬的。

那么,你应该怎么做?

定义您自己的线路格式。

  • unsigned 32 位整数将很容易编组。
  • 字符串比较难。你有一个从不属于字符串的哨兵值吗?
    或者您是否必须使用/首选计数字符串,在这种情况下您必须决定大小的类型并首先编组?

    另外,不要忘记字符集:首选 UTF-8,但如果它仅适用于 Windows,UTF-16 little-endian 也可能是一个可行的选择。

【讨论】:

  • 你的解释真的很有帮助,现在我知道问题出在哪里了,但我还没弄清楚该怎么办?你能在这方面提供更多帮助吗?
  • Alan 刚刚发布了两个专门研究此类的库。
【解决方案2】:

这很快就会变得非常复杂。

您可能想查看一些可以提供帮助的库 - Google Protobuf 和 Apache Thrift 立即浮现在脑海。两者都支持 C++ 和 C# 以及其他语言。

【讨论】:

  • 谢谢。我会测试它并告诉你结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-13
  • 2020-04-16
  • 1970-01-01
相关资源
最近更新 更多