Копировать данные из IntPtr в IntPtr
У меня два IntPtr
значения, указывающие на некоторые области данных length
байт. length
может иметь порядок от 200 до 400 тысяч.
int length = /* ..*/
IntPtr ptrSrc = /*.. */;
IntPtr ptrDst = /* .. */;
Теперь я хочу скопировать данные из ptrSrc
в ptrDst
, Этот код работает нормально:
byte[] data = new byte[length];
Marshal.Copy(ptrSrc, data, 0, length);
Marshal.Copy(data, 0, ptrDst, length);
но у него есть недостаток в необходимости дополнительного временного (потенциально огромного) массива. К сожалению, я не смог найти Marshal.Copy
вариант в.NET Framework для копирования напрямую из IntPtr
в IntPtr
Поэтому я ищу альтернативы.
Меня интересует решение, которое работает как на 32-х, так и на 64-битных Windows. Какие-либо предложения?
4 ответа
Вы можете P/Invoke в соответствующую функцию C. Это, наверное, самый простой способ сделать это. Пример:
class Program
{
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
static void Main()
{
const int size = 200;
IntPtr memorySource = Marshal.AllocHGlobal(size);
IntPtr memoryTarget = Marshal.AllocHGlobal(size);
CopyMemory(memoryTarget,memorySource,size);
}
}
Я думаю, что ответ требует обновления в.net 4.6 есть
Buffer.MemoryCopy Method (Void*, Void*, Int64, Int64)
Этот метод копирует байты sourceBytesToCopy с адреса, указанного источником, по адресу, указанному адресатом. Если буферы перекрываются и разница между адресатом минус источник меньше, чем sourceBytesToCopy, исходный блок копируется в блок назначения в обратном порядке.
Так что, если вы не используете 4.6 или универсальное приложение для Windows 10, используйте предыдущий ответ.
Как указывает пользователь 38000527, современный ответ - MemoryCopy, и он является частью.NET core 1.0, .NET standard 1.3 и.NET framework 4.6.
Вот как вы используете это в вашем контексте:
Buffer.MemoryCopy(ptrSrc.ToPointer(), ptrDest.ToPointer(), length, length)
Старый вопрос, новый ответ..
С использованиемSpan<T>
отлично работает и ОЧЕНЬ быстро. Платформа независима.
Лучший способ в dotnet core 2.1 и выше:
var srcSpan = new Span<byte>(srcPtr, count);
var dstSpan = new Span<byte>(dstPtr, count);
srcSpan.CopyTo(dstSpan);
Или, упрощенно:
public static void CopyMemory(void* srcPtr, void* dstPtr, int count) =>
new Span<byte>(srcPtr, count).CopyTo(new Span<byte>(dstPtr, count));