我正在将旧的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 。
对于如何做到这一点的任何建议将不胜感激。
答案 0 :(得分:13)
如果您对不安全的代码感到满意,并将您的类更改为结构,则可以使用fixed size buffers:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct SomeBytes
{
public fixed byte MessageData[320];
}
就个人而言,如果可能,我会尝试以避免所有这些。如果您只是通过网络发送数据,为什么还需要“进入非托管空间”?你能以某种方式删除该要求吗? (也许这是根本性的 - 但你的问题并不清楚。)
答案 1 :(得分:11)
您可以使用固定大小的数组:
unsafe struct SomeBytes {
public fixed byte b[320];
}
答案 2 :(得分:7)
我想你想做这样的事情:
[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属性告诉编组人员在编组数据时使用什么固定大小的缓冲区。
您不需要使用不安全的fixed关键字来执行此类操作,我强烈建议您避免使用它。