c# 与C++的交叉使用

//////////////////////////使用固定的{},Marshal.AllocHGlobal()和GCHandle.Alloc()的描述

使用固定的{},Marshal.AllocHGlobal()和GCHandle.Alloc()的描述.然而,我还没有找到一个简明扼要的说明,说明何时使用元帅类与GCHandle类(使用和不使用fixed {}).

我正在使用第三方.NET库,它在“缓冲区”类中有一个名为Readline()的方法.手册显示以下功能原型:

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() 

这可能是故事的结尾(而且我还没有测试上面的代码),但是我最后在Google的GCHandle类中搜索到了这个类,这让我走下了.NET互操作性,pInvoke等的路径.

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

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

并将其传递到ReadLine()?

2)我还可以使用以下代码片段(从Web上的示例中提取和调整):

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,而不是字节*.并且您必须更改编译设置以允许不安全的关键字.否则效率不高.

发布了16 篇原创文章 · 获赞 44 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/Game_jqd/article/details/89184922
C#
今日推荐