C# 正在将托管字节[]转换为结构[]
考虑以下代码作为在C# 正在将托管字节[]转换为结构[],c#,.net,struct,casting,pinvoke,C#,.net,Struct,Casting,Pinvoke,考虑以下代码作为在struct[]和byte[]之间复制内存的示例。内存复制的方法与核心问题无关。它演示了指向托管数组的两个指针 [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] public static extern void CopyMemory (IntPtr dest, IntPtr src, uint count); public struct MyStruct { public
struct[]
和byte[]
之间复制内存的示例。内存复制的方法与核心问题无关。它演示了指向托管数组的两个指针
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory (IntPtr dest, IntPtr src, uint count);
public struct MyStruct { public float Value; public TimeSpan Value; }
var bufferSize = 1000000;
var size = Marshal.SizeOf(typeof(MyStruct));
var bufferSource = new MyStruct [bufferSize];
var bufferTarget = new byte [bufferSize * size];
for (int i = 0; i < bufferSource.Length; i++)
{
bufferSource [j] = new MyStruct() { Value = i; };
}
var handleSource = GCHandle.Alloc(bufferSource, GCHandleType.Pinned);
var handleTarget = GCHandle.Alloc(bufferTarget, GCHandleType.Pinned);
var pointerSource = handleSource.AddrOfPinnedObject();
var pointerTarget = handleTarget.AddrOfPinnedObject();
handleSource.Free();
handleTarget.Free();
CopyMemory(pointerTarget, pointerSource, (uint) (bufferSize * size));
[DllImport(“kernel32.dll”,EntryPoint=“CopyMemory”,SetLastError=false)]
公共静态外部无效CopyMemory(IntPtr dest、IntPtr src、uint count);
public struct MyStruct{public float Value;public TimeSpan Value;}
var bufferSize=1000000;
var size=Marshal.SizeOf(typeof(MyStruct));
var bufferSource=newmystruct[bufferSize];
var bufferTarget=新字节[bufferSize*size];
for(int i=0;i
IntPtr
pointerTarget
不是作为MyStruct[]
发起的。是否有方法将此已分配和初始化的内存强制转换为MyStruct[]
?我不想分配一个新的数组来执行此操作。重新定义p/invoke签名更容易,在这种情况下,如下所示:
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
private static extern void CopyMemory([In, Out] byte[] pdst, Mystruct[] psrc, int cb);
CopyMemory(bufferTarget, bufferSource, bufferTarget.Length);
定义p/invoke的结构布局:
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct { public float Value; public TimeSpan Value;}
然后你可以这样使用它:
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
private static extern void CopyMemory([In, Out] byte[] pdst, Mystruct[] psrc, int cb);
CopyMemory(bufferTarget, bufferSource, bufferTarget.Length);
你有没有尝试过改编这个-?@EugenePodskal:这个例子似乎是关于字节和结构之间的转换。这如何应用于将
字节[]
表示为结构[]
?也许我遗漏了什么。如果你能从byte[]
中获得struct
,并且你知道结构的大小,那么从byte[]
中获得多个struct
有什么问题吗?@EugenePodskal:一次只给我一个struct
。我的问题是如何以struct[]
的形式访问内存,而不必重新分配内存(对于每个结构,使用PtrToStructure
会发生这种情况)。部分理解,但你最好修改你的问题,以更清楚地表达你的目标,因为对我来说,这有点模糊和误导。那么,在C#代码中进行这种操作的原因是什么?指针通常在PInvoke中使用,.NET封送处理功能非常适合处理本机结构的数组。由于您使用的是RtlMoveMemory
,因此我假设地址重叠不是问题。此签名的目标为字节[]
。是否可以交换源和目标类型?如果是这样,那是因为存在这样的签名,还是因为运行时在内部负责封送处理?当然可以交换参数。这里没有编组。CLR只在您定义签名时使用它,并相应地发送内容。它几乎什么也不检查。由于您进入了非托管世界,如果签名错误,您将得到异常、错误,您可能会弄乱内存等等。在这里,因为它们被定义为数组,所以它将这些数组作为指针传递;您可以在以下位置查看文档:和