我正在做一个实验,作为R& S的一部分。 D过程。我需要能够在结构中设置值并检索并将它们设置为byte []。
这是我的结构:
[StructLayout(LayoutKind.Explicit, Size = 17)]
unsafe internal struct MyBuffer
{
[FieldOffset(0)]
internal fixed byte Bytes[17];
[FieldOffset(0)]
internal long L1;
[FieldOffset(8)]
internal long L2;
[FieldOffset(16)]
internal byte B;
}
设置值显然会自动设置字节[]:
MyBuffer test = new MyBuffer();
test.L1 = 100;
test.L2 = 200;
test.B = 150;
在调试模式下检查测试会产生我期望的结果。
我需要的是:
注意:
答案 0 :(得分:2)
您已经在使用不安全的代码了,为什么不简单地获取指向结构的指针并传递它?这不行吗?
MyBuffer bf = new MyBuffer();
bf.L1 = 23;
unsafe
{
MyBuffer* pStruct = &bf;
YourNativeMethod(pStruct);
}
[DllImport]
static extern void YourNativeMethod(MyBuffer* pStruct);
为了避免所有编组,您可能必须编写C ++ / CLI包装器,即使您传递了不安全的指针,我也不确定.NET是否会进行编组。
您甚至不需要字节数组,本机方法当然不关心您是否将指针传递给字节数组或结构。一切都是字节数组:D
编辑:由于你的案例没有明确地调用本机方法,我们必须解决这个问题。
问题是,固定byte []实际上根本不是字节数组。它只是一个17字节的序列,仅此而已。这对于.NET数组来说还不够。所以我们必须将它复制到一个新的数组(保持“缓冲区”字节数组准备好并回收它们以避免分配和解除分配可能是值得的)。这可以通过Marshal.Copy
或一些不安全的指针乐趣来完成:
byte[] bytes = new byte[17];
unsafe
{
IntPtr srcPtr = new IntPtr(bf.Bytes);
{
Marshal.Copy(srcPtr, bytes, 0, 17);
}
}
这使用直接内存复制,但会进行一些检查。在我的测试中,这是一个很好的方法来复制更大的数组(对我来说,收支平衡点大约是50字节)。如果您的阵列较小,那么与总复制时间相比,这些检查的开销会更高,因此您可能希望使用逐字节复制:
byte[] bytes = new byte[17];
unsafe
{
byte* srcPtr = bf.Bytes;
fixed (byte* bPtr = bytes)
{
var j = 0;
while (j++ < 17)
{
*(bPtr + j) = *(srcPtr++);
}
}
}
我希望我不必告诉你要小心这种代码:)
在任何情况下,我都不会过分担心性能而且我会使用Marshal.Copy
变体,因为无论如何你的数据库调用都将成为瓶颈。更安全的选择更好:)
还可以使用一些技巧来加快速度,例如一次复制整个int
或long
,虽然它比较复杂但CPU要好得多。尝试使用一个简单的变体(长度为4的倍数,一次复制整个int)会将我的测试运行时间减少4。如果您的数据长度不是4的倍数,则只需将余数复制为字节。