简体   繁体   中英

How do I make fixed-size byte array user type in C#?

I'm converting an old Visual BASIC program to C#. It sends messages to some industrial machinery over ethernet. To do this it assembles a stream of bytes from fixed-size user defined chunks.

Most of these chunks are small and in C# it's easy to create structs of a few bytes or ints and control their size and layout using StructLayout's, for example

[StructLayout(LayoutKind.Sequential, Pack = 1)]

...so when we go into unmanaged space to do a bytewise copy we don't have byte order or padding problems.

But some of the VB6 structures are big arrays, for example,

Private Type SEND_MSG_BUFFER_320_BYTES
    bytes(0 To 319) As Byte  '320 bytes
End Type

and I'm struggling with how to do this in C#. I can make a fixed size array in a class, eg,

  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  public class SOME_BYTES
  {
      public byte[] b = new byte[320];
  } 

but to do the byte-wise copy I need to be able to discover the size of this at runtime and System.Runtime.InteropServices.Marshal.SizeOf returns a 4 for this.

Any suggestions for how do do this will be much appreciated.

You can use fixed size buffers if you're okay with unsafe code, and changing your class into a struct:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct SomeBytes
{
    public fixed byte MessageData[320];
}

Personally I would try to avoid all of this if possible. If you're just sending the data over the network, why do you need to "go into unmanaged space"? Can you remove that requirement somehow? (Maybe it's fundamental - but it's not clear from your question.)

You can use a fixed-size array:

unsafe struct SomeBytes {
    public fixed byte b[320];
}

I think you want to do something like this:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public class SOME_BYTES
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=320)]
        public byte[] b;
    } 

You would initialise it as follows:

SOME_BYTES data = new SOME_BYTES {b = new byte[320]};

Then you can populate data.b[] and use marshalling to get the data to send. The MarshalAs attribute tells the marshaller what fixed size buffer to use when marshalling the data.

You don't need to use the unsafe fixed keyword to do this kind of thing, and I strongly recommend that you avoid it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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