struct c#

时间:2017-09-18 12:46:11

标签: c# arrays struct

我在嵌入式MCU中有一个C结构,大约有1000个元素,它包含许多固定大小的数组和其他结构,现在我想用C#将数据带到PC上

这是C

中我的struct元素的简单预览
struct _registers
{
    char name[32];
    float calibrate[4][16];
    float DMTI;
    float DMTII;
    float DMTIII;
    float DMTIE;
    float DMTIIE;
    ....
};

现在我想使用GCHandle类将Struct转换为C#,

类似这样的事情

//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();

问题是Visual Studio抱怨“指针和固定大小的缓冲区只能在不安全的环境中使用”

有没有办法在没有不安全代码的情况下正常使用它?我发现做这样的事情

[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];
}

但是随着MCU上的代码在未来几年不断发展,我们将为Struct添加许多功能和参数,并且由于结构已经有1000个元素,我们如何才能更好,更聪明地做到这一点?因为跟踪所有偏移非常困难且容易出错!

1 个答案:

答案 0 :(得分:0)

尝试做一些这样的事情(注意:使用class而不是struct这更适合C# - 仍然可以编组好C ++结构):

[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
}

您将无法删除SizeConst,因为编组需要知道这一点。

此外,当您初始化该类时,您需要将数组字段设置为适当大小的缓冲区,并使用正确的缓冲区大小初始化StringBuilder

这样做意味着您可以避免使用fixed缓冲区(因此,您可以避免使用unsafe代码。)