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,而不是字節*.並且您必須更改編譯設置以允許不安全的關鍵字.否則效率不高.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章