C# 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 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语言中创建托管的Byth[]代码/>代码,预先分配给C++代码所需的大小,并使用该类型来对其进行编码并提供指针到C++代码。

您应该确实复制数据,因为ItpTr> /Cuff>指向非托管内存!谢谢您的快速回复,但是IntPtr从C++导出函数返回,所以我可以在任何我想要的地方管理和删除它。我不想复制数据,因为数据是视频缓冲区,所以它非常大。复制会使性能变差。非常感谢。这真的没有理由采取不安全的做法。。。你真的应该复制内容-有几种安全的方法可以做到这一点(有些比其他方法快)。@Yahia如果合同和生命周期定义得很好,我不确定什么会使它“不安全”,除了关键字。(在这两种情况下,它本质上都是“不安全”的内存访问。)如果性能如此关键,您是否希望转移到托管代码?即使是“不安全”的东西?啊,不安全的东西。是的,你可以用不安全的东西。你真的想要不安全的东西吗?不确定,不是我的问题:)但看看如何做到这一点会很有趣,即使有很大的警告标志。如果你让所有访问这个缓冲区的代码都不安全,并做指针算术,你可以做到这一点。但是在C++中做简单的事情并不容易。你应该提到这需要在函数签名中或者在一对大括号内的<代码>不安全的<代码>关键字:<代码> USAFE {…} /Cord:>谢谢,我刚刚尝试过。但是编译器在构建“指针和固定大小的缓冲区只能在不安全的上下文中使用”时抛出了错误。我不明白这个错误,请给我解释一下。谢谢您的项目需要配置为允许不安全的代码,答案中的代码需要包装为不安全的(正如@MikeBantegui所说),最重要的是,这为您提供了指向非托管内存的非托管指针,而不是CLR字节[] reference@random65537
fixed
在这里既不需要也不可能。感谢您的详细解释,我使用了不安全的代码:)