简体   繁体   English

将C ++结构转换为C#结构

[英]Convert C++ struct to C# struct

I need to convert a struct to bytes so that I can send or receive it over a network. 我需要将一个结构转换为字节,以便可以通过网络发送或接收它。

Let's say the struct is something like below: 假设该结构如下所示:

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

I have the equivalent struct in C# sharp which is: 我在C#Sharp中有等效的结构,它是:

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

To convert the C# struct to byte I use the this method: 要将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;
    }

And to Convert the received bytes to C++ struct I use this method: 要将接收到的字节转换为C ++结构,请使用以下方法:

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

    return info;
}

My problem is that the Age field of the struct converts very well but the Name field never is what has been sent. 我的问题是该结构的Age字段转换得很好,但是Name字段从未发送过。

Update 更新资料

I can easily convert a string to bytes using the code below and send it from c# client app to c++ server app. 我可以使用下面的代码轻松地将字符串转换为字节,并将其从c#客户端应用程序发送到c ++服务器应用程序。

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

so I decided to change the C# struct as below: 所以我决定如下更改C#结构:

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

but in this case the GetBytes() method crashes. 但是在这种情况下,GetBytes()方法会崩溃。

  1. Your C++-structure uses a flexible array member as the last element, which is an extension borrowed from C99: 您的C ++结构使用一个灵活的数组成员作为最后一个元素,它是从C99借来的扩展:

    In essence, it means that an array of unknown length ends it. 本质上,这意味着长度未知的数组将其终止。
    Because the length is not known, the compiler will, when asked for the structures size, assume 0 . 由于长度未知,因此在要求结构大小时,编译器将假定0
    I somehow doubt that's what you wanted. 我以某种方式怀疑那是您想要的。

  2. Your C#-structure has a string -member, which is not a value-type. 您的C#结构具有string -member,它不是值类型。

    Just copying the managed pointer to it like you do is quite nonsensical. 像您一样将托管指针复制到它完全是荒谬的。

So, what should you do? 那你该怎么办?

Define your own wire-format. 定义自己的线格式。

  • An unsigned 32-bit integer will be easily marshalled. unsigned 32位整数将很容易编组。
  • The string is more difficult. 字符串比较困难。 Do you have a sentinel-value never part of the string? 您是否有一个永远不属于字符串的哨兵值?
    Or do you have to use / prefer counted strings, in which case you have to decide what type the size will be and marshal that first? 还是您必须使用/首选计数字符串,在这种情况下,您必须确定大小为哪种类型并首先将其编组?

    Also, don't forget the character-set: Prefer UTF-8, though if it's windows-only, UTF-16 little-endian may also be a viable choice. 另外,请不要忘记字符集:最好使用UTF-8,尽管如果它仅用于Windows,则UTF-16 little-endian也是一个可行的选择。

This can get very complicated very quickly. 这很快就会变得非常复杂。

You might want to look at some libraries that can help - Google Protobuf and Apache Thrift immediately spring to mind. 您可能想看看一些可以提供帮助的库-立即想到Google ProtobufApache Thrift Both support C++ and C# amongst other languages. 两者都支持C ++和C#等语言。

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

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