我在嵌入式 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;
....
};
Run Code Online (Sandbox Code Playgroud)
现在我想使用 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();
Run Code Online (Sandbox Code Playgroud)
问题是 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];
}
Run Code Online (Sandbox Code Playgroud)
但是随着 MCU 上的代码在未来几年不断发展,我们将向 Struct 添加大量功能和参数,并且由于该结构已经有 1000 个元素,我们如何才能做得更好更聪明?因为跟踪所有偏移量非常困难且容易出错!
尝试做这样的事情而不是(注意:使用class而不是struct哪个更适合 C# - 仍然可以将 OK 编组到 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
}
Run Code Online (Sandbox Code Playgroud)
您将无法删除 ,SizeConst因为编组需要知道这一点。
此外,当您初始化类时,您需要将数组字段设置为适当大小的缓冲区,并StringBuilder使用正确的缓冲区大小初始化。
这样做意味着您可以避免使用fixed缓冲区(因此,您可以避免使用unsafe代码)。
| 归档时间: |
|
| 查看次数: |
8359 次 |
| 最近记录: |