Serialization / sorting of simple objects in C # for sending over the network, for an unmanaged C ++ application for reading

I am writing a C # application that should communicate with an unmanaged C ++ application over the network using predefined messages. Each message begins with an identifier and message length.

Byte 0  MessageId
Byte 1  Length

After that, for each message it is different. For example, a message to set the time will be

Byte 0      MessageId
Byte 1      Length
Byte 2..5   Time

Starting up, I decided that I was just creating a base class that inherits all other messages, which has a way to “serialize” it:

public class BaseMessage
{
    public virtual byte MessageId { get; }
    public virtual byte Length { get; }

    public byte[] GetAsMessage()
    {
        ...
    }
}

public class SetTimeMessage : BaseMessage
{
    public override byte MessageId => 1;
    public override byte Length {get; private set; }
    public byte[] Time {get; private set; }

    public SetTimeMessage(byte[] time)
    {
        ...
    }
}

In C ++ code, if I create SetTimeMessageand want to send it over the network, a method of the type GetAsMessageis defined that is defined in the base class, which simply copies the contents of the object to the buffer. This works for all derived types BaseMessage.

- #? [Serializable] BinaryFormatter, , 6 , .

Marshalling, ? , , , ( , ).

, . - , , ?

Edit

Spo1ler.

,

public interface IMsg
{
    byte MessageId { get; }
    byte Length { get; }
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SetTime: IMsg
{
    public byte Id { get; }
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public byte[] Time;

    public StartLoggerWithSampleInterval(byte time)
    {
        Id = (byte) MessageType.SetTime;
        Time = time;
    }
}

:

public static class MessageSerializer
{
    public static byte[] Serialize(IMsg msg)
    {
        int size = Marshal.SizeOf(msg);
        byte[] serialized = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.StructureToPtr(msg, ptr, true);
        Marshal.Copy(ptr, serialized, 0, size);
        Marshal.FreeHGlobal(ptr);

        return serialized;
    }
}

, , , . , ?

, (MessageId) ,

+1
1

BinaryFormatter , .NET, .. .., , .

, Plain Old Data, StructLayoutAttribute ,

[StructLayout(LayoutKind.Explicit)]
public class Message
{
    [FieldOffset(0)] public byte MessageId;
    [FieldOffset(1)] public byte Length;
    [FieldOffset(2)] public byte[] Data;
}

StructLayoutAttribute , LayoutKind.Auto , , . Explicit, .

, , , FieldOffset, , , , , .

, , yout, , .

byte, -

byte[] GetBytes(Message message) {
    int size = Marshal.SizeOf(message);
    byte[] arr = new byte[size];
    IntPtr ptr = Marshal.AllocHGlobal(size);

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

    return arr;
}

,

Message FromBytes(byte[] bytes) {
    Message message = new Message();

    int size = Marshal.SizeOf(message);
    IntPtr ptr = Marshal.AllocHGlobal(size);

    Marshal.Copy(arr, 0, ptr, size);

    message = (Message)Marshal.PtrToStructure(ptr, message.GetType());
    Marshal.FreeHGlobal(ptr);

    return message;
}

, , , , , , .

, . , , - , . , , , .

+3

All Articles