C# IntPtr可以在不进行封送处理的情况下转换到字节数组中吗?
我想从一个IntPtr指针获取数据到一个字节数组中。我可以使用以下代码执行此操作:C# IntPtr可以在不进行封送处理的情况下转换到字节数组中吗?,c#,.net,intptr,C#,.net,Intptr,我想从一个IntPtr指针获取数据到一个字节数组中。我可以使用以下代码执行此操作: IntPtr intPtr = GetBuff(); byte[] b = new byte[length]; Marshal.Copy(intPtr, b, 0, length); 但是上面的代码强制执行从IntPtr到字节数组的复制操作。当涉及的数据很大时,这不是一个好的解决方案 有没有办法将IntPtr强制转换为字节数组?例如,以下工作是否可行: byte[]b=(byte[])intPtr 这将消除复制
IntPtr intPtr = GetBuff();
byte[] b = new byte[length];
Marshal.Copy(intPtr, b, 0, length);
但是上面的代码强制执行从IntPtr到字节数组的复制操作。当涉及的数据很大时,这不是一个好的解决方案
有没有办法将IntPtr强制转换为字节数组?例如,以下工作是否可行:
byte[]b=(byte[])intPtr
这将消除复制操作的需要
另外:如何确定IntPtr指向的数据长度?受管阵列不能占用非受管内存。您可以一次将非托管数据复制一个块,然后处理每个块,或者创建一个
UnmanagedArray
类,该类接受IntPtr
,并提供一个索引器,该索引器仍将使用Marshal.copy访问数据
正如@Vinod所指出的,您可以使用unsafe
code来实现这一点。这将允许您使用类似C的指针直接访问内存。然而,在调用任何不安全的.NET方法之前,您需要将数据封送到托管内存中,因此您几乎只能使用自己的类C代码。我不认为你应该为此而烦恼,只要在C++中写代码。 试试这个:
byte* b = (byte*)intPtr;
需要(在函数签名、块或编译器标志中)。请查看此页,以获取处理非托管数组的解决方案。正如其他人所提到的,如果不复制(使用您提供的当前结构*),您无法将数据存储在托管
字节[]
中。但是,如果您实际上不需要将其放在托管缓冲区中,则可以使用不安全的
操作直接处理非托管内存。这真的取决于你需要用它做什么
所有byte[]
和其他引用类型都由CLR垃圾回收器管理,这就是不再使用时负责内存分配和释放的原因。返回的代码<代码> GetBuffer <代码>是由C++代码分配的非托管内存块,(内存布局/实现细节除外)与GC管理的内存基本上是完全分离的。因此,如果您想使用GC管理的CLR类型(byte[]
)来包含当前保存在由IntPtr
指向的非托管内存中的所有数据,则需要将其移动(复制)到GC知道的内存中。这可以通过Marshal.Copy
或使用unsafe
code或pinvoke等自定义方法完成
然而,这取决于你想用它做什么。你提到了视频数据。如果要对数据应用某些转换或筛选,可能可以直接在非托管缓冲区上执行。如果要将缓冲区保存到磁盘,可以直接在非托管缓冲区上执行
关于长度,除非分配缓冲区的函数也告诉您缓冲区的长度,否则无法知道非托管内存缓冲区的长度。正如评论者所提到的,这可以通过多种方式实现(结构的第一个字段,方法的out参数)
最后,如果你对C++代码有控制,那么可以修改它,这样它就不必分配它写入数据的缓冲区,而是提供一个指向预先分配的缓冲区的指针。然后,您可以在C语言中创建托管的
fixed
在这里既不需要也不可能。感谢您的详细解释,我使用了不安全的代码:)