可以IntPtr的被扔进一个字节数组没有做Marshal.Copy?数组、字节、扔进、IntPtr

2023-09-03 00:22:40 作者:失眠夜晚

我想从一个IntPtr指针数据一个字节数组。我可以使用下面的code做到这一点:

I want to get data from an IntPtr pointer into a byte array. I can use the following code to do it:

IntPtr intPtr = GetBuff();
byte[] b = new byte[length];
Marshal.Copy(intPtr, b, 0, length);

但上面的code强制从IntPtr的复制操作入字节数组。这不是一个很好的解决方案时所涉及的数据是很大的。

But the above code forces a copy operation from IntPtr into the byte array. It is not a good solution when the data in question is large.

有没有什么办法可以投一个IntPtr字节数组?例如,将以下工作:

Is there any way to cast an IntPtr to a byte array? For example, would the following work:

字节[] B =(字节[])的IntPtr

此将不再需要复制操作

另外:我们如何能够确定数据的长度的IntPtr指向

Also: how can we determine the length of data pointed to by IntPtr?

推荐答案

正如其他人所说,是没有办法,你可以将数据存储在一个的管理的字节[] 无复制(用您提供*目前的结构)。但是,如果你没有真正的需要的它是一个管理的缓冲区,可以使用不安全操作直接与非托管内存的工作。这真的取决于你需要做的吧。

As others have mentioned, there is no way you can store the data in a managed byte[] without copying (with the current structure you've provided*). However, if you don't actually need it to be in a managed buffer, you can use unsafe operations to work directly with the unmanaged memory. It really depends what you need to do with it.

所有字节[]等的引用类型由CLR垃圾收集管理,而这也正是负责记忆和释放分配时不再使用。内存指向的GetBuffer 的回报,这是不受管理的内存由C ++ code和(内存布局/执行细节除外)分配块本质上是完全独立的,以您的GC管理内存。因此,如果你想使用GC管理的CLR类型(字节[] )通过你的 IntPtr的,它需要被移动(复制)到存储器中由GC知道。这可以通过 Marshal.Copy 完成或自定义的方法,使用不安全 code或PInvoke的还是什么都你。

All byte[] and other reference types are managed by the CLR Garbage Collector, and this is what is responsible for allocation of memory and deallocation when it is no longer used. The memory pointed to by the return of GetBuffer is a block of unmanaged memory allocated by the C++ code and (memory layout / implementation details aside) is essentially completely separate to your GC managed memory. Therefore, if you want to use a GC managed CLR type (byte[]) to contain all the data currently held within your unmanaged memory pointed to by your IntPtr, it needs to be moved (copied) into memory that the GC knows about. This can be done by Marshal.Copy or by a custom method using unsafe code or pinvoke or what have you.

不过,这取决于你想用它做什么。你提到了它的视频数据。如果要应用一些变换或过滤器的数据,你也许可以直接在非托管缓冲区做到这一点。如果您想保存中buffer to disk,你也许可以直接在非托管缓冲区做到这一点。

However, it depends what you want to do with it. You've mentioned it's video data. If you want to apply some transform or filter to the data, you can probably do it directly on the unmanaged buffer. If you want to save the buffer to disk, you can probably do it directly on the unmanaged buffer.

在长的话题,也没有办法知道非托管内存缓冲区的长度,除非分配的缓冲区的功能也会告诉你的长度是什么。这可以通过很多方式进行,因为评论者都提到(第一结构的领域,走出paramtere的方法)。

On the topic of length, there is no way to know the length of an unmanaged memory buffer unless the function that allocated the buffer also tells you what the length is. This can be done in lots of ways, as commenters have mentioned (first field of the structure, out paramtere on the method).

*最后,如果你有C ++ $ C $的控制c。有可能修改它,使得它不负责分配它的数据写入缓冲器,而是设置有一个指向preallocated缓冲区。然后,您可以创建一个管理的字节[] 在C#,preallocated被你的C ++ code需要的尺寸,并使用在GCHandle输入引脚,并提供指针到C ++ code。

*Finally, if you have control of the C++ code it might be possible to modify it so that it is not responsible for allocating the buffer it writes the data to, and instead is provided with a pointer to a preallocated buffer. You could then create a managed byte[] in C#, preallocated to the size required by your C++ code, and use the GCHandle type to pin it and provide the pointer to your C++ code.