我想从IntPtr指针获取数据到字节数组.我可以使用以下代码来执行此操作:
IntPtr intPtr = GetBuff();
byte[] b = new byte[length];
Marshal.Copy(intPtr, b, 0, length);
Run Code Online (Sandbox Code Playgroud)
但是上面的代码强制从IntPtr到字节数组的复制操作.当有问题的数据很大时,这不是一个好的解决方案.
有没有办法将IntPtr转换为字节数组?例如,以下工作:
byte[] b = (byte[])intPtr
这将消除复制操作的需要.
另外:我们如何确定IntPtr指向的数据长度?
jef*_*ora 23
正如其他人所提到的,没有办法可以在没有复制的情况下将数据存储在托管中 byte[](使用您提供的当前结构*).但是,如果您实际上不需要它在托管缓冲区中,则可以使用unsafe操作直接使用非托管内存.这真的取决于你需要做什么.
所有byte[]和其他引用类型都由CLR垃圾收集器管理,这是在不再使用时负责内存分配和释放的原因.返回指向的内存GetBuffer是由C++代码分配的非托管内存块,(除了内存布局/实现细节)基本上与GC托管内存完全分开.因此,如果要使用GC托管CLR类型(byte[])来包含当前保存在您指向的非托管内存中的所有数据IntPtr,则需要将其移动(复制)到GC知道的内存中.这可以Marshal.Copy通过自定义方法unsafe或使用代码或pinvoke或您拥有的内容来完成.
但是,这取决于你想用它做什么.你已经提到了它的视频数据.如果要对数据应用某些转换或过滤器,则可以直接在非托管缓冲区上执行此操作.如果要将缓冲区保存到磁盘,则可以直接在非托管缓冲区上执行此操作.
关于长度的主题,除非分配缓冲区的函数也告诉您长度是多少,否则无法知道非托管内存缓冲区的长度.这可以通过许多方式完成,正如评论者所提到的(结构的第一个领域,方法的参数).
*最后,如果您可以控制C++代码,则可以对其进行修改,以便它不负责分配将数据写入的缓冲区,而是提供指向预分配缓冲区的指针.然后,您可以在C#中创建托管 byte[],预分配到C++代码所需的大小,并使用该GCHandle类型来固定它并提供指向C++代码的指针.
试试这个:
byte* b = (byte*)intPtr;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
22063 次 |
| 最近记录: |