2013-04-12 26 views
24

Ho due valori IntPtr che indicano alcune aree di dati di length byte. length potrebbe avere un ordine di grandezza compreso tra 200k e 400k.Copia dati da IntPtr a IntPtr

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

Ora voglio copiare i dati ptrSrc-ptrDst. Questo codice funziona correttamente:

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

ma ha lo svantaggio di aver bisogno di un ulteriore array temporaneo (potenzialmente enorme). Purtroppo, non sono riuscito a trovare una variante Marshal.Copy nel framework .NET per copiare direttamente da IntPtr a IntPtr, quindi sono alla ricerca di alternative.

Sono interessato a una soluzione che funziona su Windows 32 e Windows a 64 bit. Eventuali suggerimenti?

+1

È possibile utilizzare 'non sicuro? – driis

+0

@driis: sì, è possibile. –

risposta

32

È possibile P/Invoke nella funzione C appropriata. Questo è probabilmente il modo più semplice per farlo. Esempio:

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, funzionerà su 32 e Windows a 64 bit? –

+0

Sì. 'memcpy' copia i byte, quindi non ci sono problemi di dimensione del puntatore o di limiti di parole. C# marhsalling si prenderà cura di fornire la giusta dimensione del puntatore alla funzione C sottostante. – driis

+0

E posso supporre che msvcrt sia installato sulla macchina degli utenti, o devo fornire il mio? Voglio dire, ci sono diversi msvcrt.dll per 32 e 64 bit di Windows, giusto? Non sono preoccupato per le dimensioni del puntatore. –

3

Credo la risposta necessita di un aggiornamento NET 4.6 c'è

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

Questo metodo copia sourceBytesToCopy byte dall'indirizzo specificato dalla sorgente all'indirizzo specificato di destinazione. Se i buffer si sovrappongono e la differenza tra l'origine meno della destinazione è inferiore a sourceBytesToCopy, il blocco di origine viene copiato nel blocco di destinazione in ordine inverso.

Quindi, se non si è in 4.6 o l'app universale di Windows 10, utilizzare la risposta precedente.

+0

Grazie per questo aggiornamento. Sicuro che questa soluzione funzioni anche per le app UWP? Immagino che la risposta accettata no. –

+0

Ha richiesto il blocco di codice 'non sicuro' per funzionare. – SMUsamaShah

+0

Sì, è normale quando si è in C# e si accede direttamente alla memoria. C# isnt C++ dove tali azioni sono più comuni – user3800527

Problemi correlati