Копировать данные из 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));
Другие вопросы по тегам