6

I have a C struct in an embedded MCU with about 1000 elements, and it contains lots of fixed size arrays and other structs inside, Now I want to bring the data to PC Using C#

Here is a simple preview of my struct elements in C

struct _registers
{
    char name[32];
    float calibrate[4][16];
    float DMTI;
    float DMTII;
    float DMTIII;
    float DMTIE;
    float DMTIIE;
    ....
};

Now I want to convert the Struct into C# using the GCHandle class,

something like this

//The C struct is in this byte array named buffer
byte[] buffer = new byte[4096];

        GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
       _registers stuff = (protection_registers)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(_registers));
        handle.Free();

the problem is that the Visual studio complains about the "Pointers and fixed size buffers may only be used in an unsafe context"

is there a way to use it normally without unsafe code? I have found Doing something like this

[StructLayout(LayoutKind.Explicit, Size = 56, Pack = 1)]
public struct NewStuff
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    [FieldOffset(0)]
    public string name;

    [MarshalAs(UnmanagedType.U4)]
    [FieldOffset(32)]
    public float calibrate[4][16];
}

but as the Code on the MCU is evolving in the coming years and we will add lots of functionality and parameter to the Struct, and since the struct has already 1000 elements, how we can do it better and more clever way? because keep tracking of all the offsets is very hard and error prone!

8
  • tag spamming is bad netiquette Commented Sep 18, 2017 at 12:46
  • You don't need to specify FieldOffset as long as you define the sizes of all the fields correctly (which you are doing). Commented Sep 18, 2017 at 12:48
  • You should not declare _registers as a struct if it has 1000 elements. Declare it as a class instead. Otherwise each assignment will create a new _registers copy. The difference between class and struct in C++ is not the same as the difference between class and struct in C#. Commented Sep 18, 2017 at 12:54
  • Is there a way to remove the SizeConst too? Commented Sep 18, 2017 at 12:56
  • thanks, would you give me a sniper code? Commented Sep 18, 2017 at 12:56

1 Answer 1

12

Try doing something like this instead (note: using class instead of struct which is more appropriate for C# - still marshals OK to a C++ struct):

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class NewStuff
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public StringBuilder name;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4*16)]
    public float[,] calibrate;

    [MarshalAs(UnmanagedType.R4)]
    public float DMTI;

    [MarshalAs(UnmanagedType.R4)]
    public float DMTII;

    // Etc
}

You won't be able to remove the SizeConst since the marshalling needs to know this.

Also, when you intialise the class, you will need to set the array fields to the appropriate sized buffers, and initialise the StringBuilder with the correct buffer size.

Doing it this way means you can avoid using fixed buffers (and hence, you avoid the unsafe code).

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

3 Comments

[FieldOffset] is not unsafe. His code snippet is lousy, it is missing the fixed keyword. Required to make it compile. Fixed-size buffers are unsafe, indexing them is not checked.
@HansPassant Aye, I removed my comments about FieldOffset. I'd misremembered an old discussion where someone proposed that FieldOffset should be unsafe - but of course, that never happened...
@HansPassant [FieldOffset] can be used to break .NET's type safety, at least amongst reference-types and so allows for type-punning (and not particularly useful type-puns either...), but how is that "not unsafe"?

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.