You can probably also allocate the array in managed memory, and then create a GCHandle
to allow it to be accessed from unmanaged memory.
For example, here I call PowerReadACValue
; the Win32 API function takes in an LPBYTE
buffer (which equates to BYTE*
).
First I call it with a "null pointer" (IntPtr.Zero), so that it will tell me what size buffer I need (this gets output into bufferSize). Then I allocate the buffer, and pass in the pointer via GCHandle
's AddrOfPinnedObject
.
uint type;
uint bufferSize = 0;
if (SafeNativeMethods.PowerReadACValue(IntPtr.Zero, this.m_planHandle, ref subGroupOfPowerSettingsGuid, ref powerSettingGuid, out type, IntPtr.Zero, ref bufferSize) != 0)
{
throw new Win32Exception();
}
byte[] buffer = new byte[bufferSize];
GCHandle bufferPointer = default(GCHandle);
try
{
bufferPointer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
if (SafeNativeMethods.PowerReadACValue(IntPtr.Zero, this.m_planHandle, ref subGroupOfPowerSettingsGuid, ref powerSettingGuid, out type, bufferPointer.AddrOfPinnedObject(), ref bufferSize) != 0)
throw new Win32Exception();
}
finally
{
if (bufferPointer.IsAllocated)
bufferPointer.Free();
}
Alternatively, I could have allocated the buffer with Marshal.AllocHGlobal
, which also returns me an IntPtr
, and then afterwards free it with Marshal.FreeGlobal
, but in this case I need to use the data in the array from managed code. If I were simply going to pass the array pointer to another unmanaged function without ever touching it from managed code, this would be a better way to go (while the GCHandle is active, the memory is locked into place in memory which affects the garbage collector).