c# - struct c#中的安全固定大小数组

标签 c# arrays struct

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

这是我在 C 中的结构元素的简单预览

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 上的代码在 future 几年不断发展,我们将向 Struct 添加大量功能和参数,并且由于该结构已经有 1000 个元素,我们如何才能做得更好更聪明?因为跟踪所有偏移量非常困难且容易出错!

最佳答案

尝试做这样的事情而不是(注意:使用 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 代码)。

关于c# - struct c#中的安全固定大小数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46279646/

相关文章:

c# - 谷歌分析类似工具

c++ - 在对象内创建对象数组时的默认构造函数

c - 从不兼容的指针类型初始化 - C 结构

c - 最长递增子序列中的荒谬条件

java - Java 中的子字符串替换

c - 在c中初始化一个新结构

dictionary - 如何在Go中使用空结构值制作 map

c# - 如何从标志枚举中获取数值?

c# - DDD - 使用聚合的 transient 验证

c# - 转换为匿名类型