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) ,