gpt4 book ai didi

c# - 了解使用固定{}、Marshal.AllocHGlobal() 和 GCHandle.Alloc() 之间的区别

转载 作者:可可西里 更新时间:2023-11-01 07:47:58 32 4
gpt4 key购买 nike

首先我要说的是,我在整个论坛和网络上的许多链接中查看并找到了有关使用 fixed{}、Marshal.AllocHGlobal() 和 GCHandle.Alloc() 的描述。但是,我还没有找到关于何时使用 Marshal 类与 GCHandle 类(使用和不使用 fixed{})的简明解释。

我正在使用第三方 .NET 库,它在“Buffer”类中有一个名为 Readline() 的方法。手册显示了以下函数原型(prototype):

bool ReadLine(int x1, int y1, int x2, int y2, System.IntPtr bufData, out int numRead);

bufData 的描述如下:...内存区域的字节数必须大于或等于行长度乘以返回值BytesPerPixel 属性。

现在在用户手册的后面,他们确实给出了一个访问缓冲区的例子(我已经为我的具体例子做了一些调整):

// Create an array large enough to hold one line from buffer
int size = 640;
byte[] dataLine = new byte[size * 2]; // 2 bytes per pixel

// Pin the array to avoid Garbage collector moving it
GCHandle dataLineHandle = GCHandle.Alloc(dataLine, GCHandleType.Pinned);
IntPtr dataLineAddress = dataLineHandle.AddrOfPinnedObject();

我可以按照上面的“示例”代码:

// Read one line of buffer data 
success = buffer.ReadLine(0, 0, 639, 0, dataLineAddress, out numRead);

// Unpin the array
dataLineHandle.Free()

这可能是故事的结尾(我还没有测试上面的代码),但我最终在谷歌上搜索了 GCHandle 类,这让我走上了 .NET 互操作性、pInvoke 等的道路。

所以我的问题...1) 为什么我不能使用:

IntPtr dataLineAddress = Marshal.AllocHGlobal( size * 2 );

并将其传递给 ReadLine()?

2) 我是否也可以使用以下代码片段(从网络上的示例中提取和调整):

int size = 640;
byte[] dataLine= new byte[size * 2]; // 2 bytes per pixel

// prevent garbage collector from moving buffer around in memory
fixed (byte* fixedDataLine = dataLine)
{
// get IntPtr representing address of first buffer element
IntPtr dataLineAddress= Marshal.UnsafeAddrOfPinnedArrayElement(fixedDataLine , 0);
success = buffer.ReadLine(0, 0, 639, 0, dataLineAddress, out numRead);
}

我希望任何人都能阐明上述技术并指出我在实现过程中的错误,并指出上述方法何时适用。最后,即使上述方法都有效,过去几年是否普遍插入了一种或另一种方法?

提前致谢!!炒作

最佳答案

好吧,替代方案也可能有效。但是 Marshal.AllocHGlobal 示例并不完整,您现在已经在非托管内存中获得了数据。您仍然需要做一些工作才能将它放入托管对象(数组)中,以便您可以轻松访问它,您必须调用 Marshal.Copy()。效率低下,因为它复制了两次数据。并且不要忘记调用 Marshal.FreeHGlobal()。

固定样本与供应商样本做同样的事情,它隐含地固定内存。这里的尴尬之处在于 API 采用 IntPtr,而不是 byte*。并且您必须更改编译设置以允许使用 unsafe 关键字。否则效率不会更高。

以不同的方式做这件事并没有领先。

关于c# - 了解使用固定{}、Marshal.AllocHGlobal() 和 GCHandle.Alloc() 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4579991/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com