2013-04-12 15 views
24

Mam dwie wartości IntPtr wskazujące na niektóre obszary danych o length bajtów. length może mieć rząd wielkości od 200k do 400k.Kopiowanie danych z IntPtr do IntPtr

  int length = /* ..*/ 
      IntPtr ptrSrc = /*.. */; 
      IntPtr ptrDst = /* .. */; 

Teraz chcę skopiować dane z ptrSrc do ptrDst. Ten kod działa poprawnie:

  byte[] data = new byte[length]; 
      Marshal.Copy(ptrSrc, data, 0, length); 
      Marshal.Copy(data, 0, ptrDst, length); 

, ale ma tę wadę, że wymaga dodatkowej tymczasowej (potencjalnie ogromnej) tablicy. Niestety, nie mogłem znaleźć wariantu Marshal.Copy w środowisku .NET do kopiowania bezpośrednio z IntPtr do IntPtr, więc szukam alternatyw.

Jestem zainteresowany rozwiązaniem, które działa na 32 Windowsach oraz 64-bitowym systemie Windows. Jakieś sugestie?

+1

Czy można użyć 'unsafe'? – driis

+0

@driis: tak, to jest możliwe. –

Odpowiedz

32

Możesz P/Inwokować do odpowiedniej funkcji C. Jest to prawdopodobnie najłatwiejszy sposób robienia tego. Przykład:

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); 
    } 
} 
+0

Hm, czy to będzie działać na 32, a także 64-bitowym systemie Windows? –

+0

Tak. 'memcpy' kopiuje bajty, więc nie ma problemów z rozmiarem wskaźnika lub słowem. C# marhsalling zajmie się dostarczeniem odpowiedniego rozmiaru wskaźnika do podstawowej funkcji C. – driis

+0

Czy mogę założyć, że msvcrt jest zainstalowany na komputerze użytkownika, czy też muszę dostarczać własne? Mam na myśli różne msvcrt.dll dla 32 i 64-bitowego systemu Windows, prawda? Nie martwię się wielkością wskaźnika. –

3

Myślę, że odpowiedź wymaga aktualizacji w .NET 4.6 istnieje

Buffer.MemoryCopy Method (Void*, Void*, Int64, Int64) 

Metoda ta kopiuje sourceBytesToCopy bajtów od adresu podanego przez źródła na adres podany przez przeznaczenia. Jeśli bufory nakładają się, a różnica między miejscem docelowym minus źródło jest mniejsza niż sourceBytesToCopy, blok źródłowy jest kopiowany do bloku docelowego w odwrotnej kolejności.

Więc jeśli nie używasz 4.6 lub uniwersalnej aplikacji Windows 10, użyj poprzedniej odpowiedzi.

+0

Dzięki za tę aktualizację. Czy to rozwiązanie sprawdza się również w aplikacjach UWP? Sądzę, że zaakceptowana odpowiedź nie będzie. –

+0

Wymagało to użycia 'bloku' 'niebezpiecznego' kodu. – SMUsamaShah

+0

Tak, to normalne, gdy jesteś w C# i masz dostęp bezpośrednio do pamięci. C# isnt C++, gdzie takie akcje są bardziej powszechne – user3800527

Powiązane problemy