2013-04-12 14 views
24

バイトのデータ領域を指す2つのIntPtrの値があります。 lengthは、200k〜400kの大きさのオーダーを有することができる。IntPtrからIntPtrへデータをコピー

  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); 

しかし、追加の一時的な(潜在的に巨大な)アレイが必要であるという欠点があります。残念ながら、IntPtrからIntPtrに直接コピーするための.NETフレームワークでMarshal.Copyの亜種が見つかりませんでしたので、代替案を探しています。

32ビットWindowsと64ビットWindowsで動作するソリューションに興味があります。助言がありますか?

+1

'unsafe'を使用できますか? – driis

+0

@driis:はい、可能です。 –

答えて

32

適切なC関数にP/Invokeすることができます。それがおそらく最も簡単な方法です。例:

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

ええと、64ビットWindowsだけでなく32でも動作しますか? –

+0

はい。 'memcpy'はバイトをコピーするので、ポインタサイズや単語境界の問題はありません。 C#marhsallingは、基礎となるC関数に正しいポインタサイズを提供するための処理を行います。 – driis

+0

また、msvcrtをユーザーマシンにインストールすることができますか、自分自身を提供する必要がありますか?つまり、32ビット版と64ビット版のWindows用に異なるmsvcrt.dllがあります。私はポインタのサイズを心配していません。 –

3

私は

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

先で指定されたアドレスへの送信元で指定されたアドレスからバイトsourceBytesToCopyこの​​方法でコピーがあります答えは、.NET 4.6での更新が必要であると思います。バッファが重複し、宛先マイナスソース間の差がsourceBytesToCopyより小さい場合、ソースブロックは宛先ブロックに逆の順序でコピーされます。

したがって、4.6またはユニバーサルウィンドウアプリ10にいない場合は、前の回答を使用してください。

+0

このアップデートをありがとう。もちろん、このソリューションはUWPアプリケーションでも機能しますか?私は受け入れられた答えはないと思います。 –

+0

'unsafe'コードブロックが動作する必要がありました。 – SMUsamaShah

+0

はい、それはあなたのC#で直接メモリにアクセスするときです。 C#ではこのようなアクションがより一般的です – user3800527