如何将Span<byte>内容复制到IntPtr指向的非托管内存?
无内存分配复制Span到非托管内存的方案
1. .NET Core 3.0+/NET 5+ 原生支持(最优解)
从.NET Core 3.0开始,Marshal.Copy新增了直接接收ReadOnlySpan<byte>的重载,无需额外内存分配,也完全不需要unsafe代码:
Span<byte> sourceSpan = ...; IntPtr targetUnmanagedPtr = ...; Marshal.Copy(sourceSpan, targetUnmanagedPtr, sourceSpan.Length);
这个重载直接操作Span的底层内存,没有中间数组的分配开销,完美匹配你的需求。
2. 旧.NET框架兼容方案(无unsafe)
如果你的项目基于.NET Framework或更早的.NET Core版本,可以尝试通过MemoryMarshal.TryGetArray获取Span对应的堆数组段(仅适用于基于堆数组的Span),再调用传统的Marshal.Copy数组重载:
Span<byte> sourceSpan = ...; IntPtr targetUnmanagedPtr = ...; if (MemoryMarshal.TryGetArray(sourceSpan, out ArraySegment<byte> segment)) { Marshal.Copy(segment.Array, segment.Offset, targetUnmanagedPtr, segment.Count); } else { // 处理非堆数组来源的Span(如栈上Span、非托管内存Span) // 若不能使用unsafe代码,此时只能退而求其次使用ToArray(),或者考虑升级.NET版本 }
注意:MemoryMarshal.TryGetArray仅对堆分配数组生成的Span有效,对于栈上分配的Span(如stackalloc byte[100])或指向非托管内存的Span,该方法会返回false,这种场景下如果严格禁用unsafe代码,暂时没有无分配的替代方案,建议优先考虑升级.NET版本。
内容的提问来源于stack exchange,提问作者FICHEKK
相关产品推荐
相关产品推荐

