Возможно, вы также можете выделить массив в управляемой памяти, а затем создать GCHandle
, чтобы разрешить доступ к нему из неуправляемой памяти.
Например, здесь я звоню PowerReadACValue
; функция Win32 API получает буфер LPBYTE
(что равно BYTE*
).
Сначала я вызываю его с помощью «нулевого указателя» (IntPtr.Zero), чтобы он сообщал мне, какой размер буфера мне нужен (это выводится в bufferSize). Затем я выделяю буфер и передаю указатель через 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();
}
Кроме того, я мог бы выделить буфер с помощью Marshal.AllocHGlobal
, который также возвращает мне IntPtr
, а затем освободить его с помощью Marshal.FreeGlobal
, но в этом случае мне нужно использовать данные в массиве из управляемого код. Если бы я просто собирался передать указатель массива на другую неуправляемую функцию, даже не прикасаясь к ней из управляемого кода, это был бы лучший путь (пока GCHandle активен, память блокируется в памяти, что влияет на сборщик мусора ).