1

What is the best way for Copying 'mydata' to 'sample_a'?

I expect to get 4 in sample_a.data_array[ 1 ]. That value is p[ 9 ].

I plan to use this for TCP/UDP packet communication.

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    public unsafe fixed char data_array[3];
    public int data3;
}

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");

    short bytesize = 15; 
    byte[] mydata = new byte[bytesize];
    unsafe
    {
        fixed (byte* p = mydata)
        {
            // data1
            p[0] = 1;
            // data2
            p[4] = 2;
            // data_array
            p[8] = 3;
            p[9] = 4;
            p[10] = 5;
            // data3
            p[11] = 6;
        }

        // Copy 'mydata' to 'sample_a'
        IntPtr intptr = Marshal.AllocHGlobal(bytesize);
        Marshal.Copy(mydata, 0, intptr, bytesize);
        SampleA sample_a = (SampleA)Marshal.PtrToStructure(intptr, typeof(SampleA));
        Marshal.FreeHGlobal(intptr);

        // I want to get 4 in a1
        int a1 = (int)sample_a.data_array[1];
    }
}

enter image description here

2
  • You could also check the MemoryMarshal.Cast this doesn't do a memory copy. Commented Feb 5, 2020 at 15:13
  • Thank you. I check your link. Commented Feb 5, 2020 at 15:39

2 Answers 2

3

You can avoid a lot of work here with spans:


// note: size is 18; if you intended 15 - perhaps change char=>byte
byte[] mydata = new byte[Unsafe.SizeOf<SampleA>()];
// alternative: Span<byte> mydata = stackalloc byte[Unsafe.SizeOf<SampleA>()];

// ..TODO: populate mydata

// cast it out
var sample_a = MemoryMarshal.Cast<byte, SampleA>(mydata)[0];

You can also use Unsafe.As, but this is IMO not a good idea as it won't detect incorrect memory conditions as well:

var sample_a = Unsafe.As<byte, SampleA>(ref mydata[0]);
Sign up to request clarification or add additional context in comments.

4 Comments

Note also that this doesn't use the marshaller, and so none of the attributes which normally affect the marshaller, e.g. MarshalAs, will do anything.
@canton7 not true; StructLayout also impacts the layout of the struct itself: so yes, it still has effect (it won't impact MarshalAs - that was a comment edit, though!)
True, bad example on my side. Changed.
@canton7 re the bytes vs char: yes, that is true; if OP intends these to be bytes: they should declare them as bytes
2

Your problem is that C#'s chars are 2 bytes wide, and you're treating them as if they're 1 byte wide.

One fix is to explicitly declare them as byte:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    public unsafe fixed byte data_array[3];
    public int data3;
}

It's more common to embed arrays using UnmanagedType.ByValArray:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] data_array;
    public int data3;
}

If you want to use char, you can tell the marshaller that each should be marshalled as a U8:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SampleA
{
    public int data1;
    public int data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U8)]
    public char[] data_array;
    public int data3;
}

You can also tell the marshaller that you're using ANSI strings, which has the same effect

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
struct SampleA
{
    public int data1;
    public int data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public char[] data_array;
    public int data3;
}

1 Comment

That is one of several ways of doing this; however, it is not the only option

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.