Let me start by saying I've looked and found descriptions of the use of fixed{}, Marshal.AllocHGlobal()and GCHandle.Alloc() throughout this forum and in many links on the web. However, I have yet to find a concise explanation of when to use the Marshal class vs. the GCHandle class (with and without using fixed{}).
I'm using a third-party .NET library which has a method called Readline() in a "Buffer" class. The manual shows the following function prototype:
bool ReadLine(int x1, int y1, int x2, int y2, System.IntPtr bufData, out int numRead);
with a description of bufData that says: ...The memory area must have a number of bytes larger than or equal to the line length times the value returned by the BytesPerPixel property.
Now later in the user manual they do give an example of accessing the buffer (which I've tweaked a little bit for my specific example):
// 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();
and I could follow the above "example" code with:
// Read one line of buffer data
success = buffer.ReadLine(0, 0, 639, 0, dataLineAddress, out numRead);
// Unpin the array
dataLineHandle.Free()
That could be the end of the story (and I have yet to test the above code), but I ended up googling the GCHandle class which drove me down the path of .NET interoperability, pInvoke, etc.
So my questions... 1) Why can't I use:
IntPtr dataLineAddress = Marshal.AllocHGlobal( size * 2 );
and pass that into ReadLine()?
2) Can I also use the following snippet of code (extracted and tweaked from examples on the 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);
}
I'd be interested in anyone can shed light on the above techniques and point out my errors in implementation as well as point out when the above methods are appropriate. Finally, even if the above methods are all valid, is there a general push in the past few years toward one approach or the other?
Thanks in advance!! Hyped