c# - 如何在 c#.net 中将结构转换为字节数组,但结构大小仅在运行时定义

标签 c# arrays byte structure marshalling

我有如下结构

[StructLayout(LayoutKind.Sequential)]
public struct MyStructType
{
[MarshalAs(UnmanagedType.U1)]
public byte stx;

public UInt16 cmdId;

public UInt16 status;

public UInt16 pktNo;

[MarshalAs(UnmanagedType.U1)]
public byte contPkt;

[MarshalAs(UnmanagedType.U1)]
public byte dataoffset;

public UInt16 dataLength;

[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)]
public byte[] data;

public UInt16 checkSum;

[MarshalAs(UnmanagedType.U1)]
public byte cr;
}

我尝试使用以下代码将此结构转换为字节数组。

byte[] ConvertStructureToByteArray(MyStructType str)
    {
        int size = Marshal.SizeOf(str);
        byte[] arr = new byte[size];

        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(str, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);
        return arr;
    }

但我得到了以下错误,因为他们不知道大小

Type 'MyStructType' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

问题是因为

public UInt16 dataLength; 
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] 
public byte[] data;

dataLength 在运行时计算。如何将此结构转换为 ByteArray?

最佳答案

编码的限制

正如您已经注意到的,Marshal.SizeOf() 无法计算包含带有 UnmanagedType.LPArraybyte 数组的结构的大小。但是,这并不意味着您不能自己计算。

但是,即使您这样做,您也会收到 Marshal.StructureToPtr 提示必须使用 SafeArray 或 ByValArray 的数据字段。

你应该检查this on MSDN为了了解如何将数组从托管传递到非托管。然而,对于结构中包含的数组,似乎:

The size can be set only as a constant

为什么不使用序列化?

Protocol Buffer 是一种将数据序列化为二进制的简单方法。此外,它还支持模型更改、模型共享和其他一些很酷的功能。

它有多种语言版本:

关于c# - 如何在 c#.net 中将结构转换为字节数组,但结构大小仅在运行时定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34308001/

相关文章:

c# - MVC4 API 路由进入第一个 Action

java - 使用字符串将 boolean 变量传递给 Arraylist

arrays - jq 查找值为包含特定元素的数组的键

Javascript 字符串对象到数组

Java 如何从接收到的 UDP 字节中解析 double 值?

ruby - Ruby 中的字节操作

c# - TFS API获取工作项数据

variables - 如何使用来自资源另一个 .cs 文件的变量与 "using"

Swift:如何将字节转换为 float /获得更精确的数字?

c# - ZXing.Net后退导航C#