Pau*_*erg 2 c# arrays struct runtime marshalling
假设我有一个类似于
public struct MyStruct
{
public float[] a;
}
Run Code Online (Sandbox Code Playgroud)
并且我想用一些自定义数组大小实例化一个这样的结构(在这个例子中假设为 2)。然后我将它编组到一个字节数组中。
MyStruct s = new MyStruct();
s.a = new float[2];
s.a[0] = 1.0f;
s.a[1] = 2.0f;
byte[] buffer = new byte[Marshal.SizeOf(typeof(MyStruct))];
GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
Marshal.StructureToPtr(s, gcHandle.AddrOfPinnedObject(), false);
for (int i = 0; i < buffer.Length; i++)
{
System.Console.WriteLine(buffer[i].ToString("x2"));
}
}
finally
{
gcHandle.Free();
}
Run Code Online (Sandbox Code Playgroud)
这在我的 byte[] 中只给了我 4 个字节,它们看起来像一个指针值,而不是 1.0f 或 2.0f 的值。我已经四处寻找使这项工作起作用的方法,但到目前为止我能找到的都是类似的例子,其中结构数组的大小是提前知道的。没有办法做到这一点吗?
在StructureToPtr与包含值类型只(INT,炭,浮点型,其他结构)的结构确实仅工作。float[]是一个引用类型,所以你真的得到了一种指针(你不能真正使用它,因为它是一个托管指针)。如果要将数组复制到固定内存,则必须Marshal.Copy直接在s.a浮点数组上使用其中一个函数。
类似的东西。(我没有真正测试过)
byte[] buffer = new byte[sizeof(float) * s.a.Length];
GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Run Code Online (Sandbox Code Playgroud)
进而
Marshal.Copy(s.a, 0, gcHandle.AddrOfPinnedObject(), s.a.Length);
Run Code Online (Sandbox Code Playgroud)
更新
我必须纠正自己。您还可以通过以这种方式声明您的结构来获得您想要的:
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public float[] a;
}
Run Code Online (Sandbox Code Playgroud)
如您所见,您必须在设计时固定浮点数组的大小。