11

我正在将旧的 Visual BASIC 程序转换为 C#。它通过以太网向某些工业机器发送消息。为此,它从固定大小的用户定义块组装字节流。

大多数这些块都很小,在 C# 中,很容易创建几个字节或整数的结构,并使用 StructLayout 控制它们的大小和布局,例如

[StructLayout(LayoutKind.Sequential, Pack = 1)]

...所以当我们进入非托管空间进行按字节复制时,我们没有字节顺序或填充问题。

但是有些 VB6 结构是大数组,例如,

Private Type SEND_MSG_BUFFER_320_BYTES
    bytes(0 To 319) As Byte  '320 bytes
End Type

我正在为如何在 C# 中做到这一点而苦苦挣扎。我可以在一个类中创建一个固定大小的数组,例如,

  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  public class SOME_BYTES
  {
      public byte[] b = new byte[320];
  } 

但要进行逐字节复制,我需要能够在运行时发现它的大小,并且 System.Runtime.InteropServices.Marshal.SizeOf 为此返回4

任何有关如何做到这一点的建议将不胜感激。

4

3 回答 3

14

如果您可以使用不安全的代码并将您的类更改为结构,则可以使用固定大小的缓冲区:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct SomeBytes
{
    public fixed byte MessageData[320];
}

如果可能的话,我个人会尽量避免所有这些。如果您只是通过网络发送数据,为什么需要“进入非托管空间”?你能以某种方式删除这个要求吗?(也许这是基本的 - 但你的问题并不清楚。)

于 2013-01-31T15:12:24.853 回答
11

您可以使用固定大小的数组:

unsafe struct SomeBytes {
    public fixed byte b[320];
}
于 2013-01-31T15:12:11.363 回答
9

我想你想做这样的事情:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public class SOME_BYTES
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=320)]
        public byte[] b;
    } 

您将按如下方式对其进行初始化:

SOME_BYTES data = new SOME_BYTES {b = new byte[320]};

然后您可以填充 data.b[] 并使用编组来获取要发送的数据。MarshalAs 属性告诉编组器在编组数据时使用什么固定大小的缓冲区。

你不需要使用不安全的固定关键字来做这种事情,我强烈建议你避免。

于 2013-01-31T15:19:02.880 回答