0

I'm working on a library that communicated with a µController via UDP-Messages. For that I'm using a custom protocol which is basically a struct consisting of 2 elements: The header (some metadata + checksum) and the payload. The communication is done via the System.Net.Sockets.UDPClient Class. To convert my data I'm using the following function:

private List<byte> GetBytes(object str) { int size = Marshal.SizeOf(str); byte[] arr = new byte[size]; IntPtr ptr = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(str, ptr, true); Marshal.Copy(ptr, arr, 0, size); Marshal.FreeHGlobal(ptr); return arr.ToList(); } 

I'm running into problems now if I want to send some payload which is not of a constant size, for example if I just want to write some data of variable length to the µController. One workaround that I am currently using is to just encapsulate my payload in a struct of a constant (maximum) size, but that seems not very efficient to me.

So, is there any way to convert a struct of a non constant-size to a Byte-Array with C#? For example this struct:

[StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct PERIPHERY__PROTOCOL { public PERIPHERY_HEADER strHeader; public byte[] Data; } 
3
  • Possible duplicate of How to convert a structure to a byte array in C#? Commented May 18, 2017 at 13:31
  • @KillerIsDead I don't think that addresses the key part of the issue here Commented May 18, 2017 at 13:33
  • Note that in your code, you are allocating some unmanaged memory, writing to it, then releasing the unmanaged memory - that... isn't actually very useful to anything Commented May 18, 2017 at 13:34

2 Answers 2

1

In your PERIPHERY__PROTOCOL example, you aren't actually putting the data into the struct - you are creating a separate array and putting the data there. You can still do that, absolutely - but you'll have to pay the heap overheads. In that case, forget about Marshal - you'd just pass arr to the struct.

But if you mean "can I have variable length structs in .NET"; no - no you cannot.

Sign up to request clarification or add additional context in comments.

Comments

1

Why you want to use a struct?

Use a class. This sample code lets you add new packet types and convert them to bytes. If you want mechanism which will convert it back (from bytes to classes), you need to add your own invention.

public abstract class Packet { public int PacketType { get; } public Packet (int packetType) { PacketType = packetType; } protected abstract byte[] GetPayload (); private int CalculateChecksum () { byte[] packetTypeBytes = BitConverter.GetBytes (PacketType); byte[] payloadBytes = GetPayload (); byte[] lengthBytes = BitConverter.GetBytes (payloadBytes.Length); return 0; // add some logic to calculate checksum from all bytes } public byte[] ToBytes () { byte[] packetTypeBytes = BitConverter.GetBytes (PacketType); byte[] checksumBytes = BitConverter.GetBytes (CalculateChecksum ()); byte[] payloadBytes = GetPayload (); byte[] lengthBytes = BitConverter.GetBytes (payloadBytes.Length); return packetTypeBytes.Concat (lengthBytes).Concat (checksumBytes).Concat (payloadBytes).ToArray (); } } public sealed class ActionA : Packet { public string Message { get; } public ActionA (string message) : base (0) { Message = message; } protected override byte[] GetPayload () { return Encoding.ASCII.GetBytes (Message); } } public sealed class ActionB : Packet { public int Value { get; } public ActionB (int value) : base (1) { Value = value; } protected override byte[] GetPayload () { return BitConverter.GetBytes (Value); } } 

2 Comments

The C Code that runs on the µController uses structs. I just copied and adapted them to my C# library
@kain: Forget about C code on controller side. Just send valid data. If you use C#, program like in C#, not like in C.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.