0
[DllImport("kernel32.dll", SetLastError=true)]
    public static extern unsafe bool WriteFile(IntPtr hFile, void* lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped);

私はこれを署名付きのWrite(..)メソッドを介して実装しています:

Write(IntPtr handleFile, void* bufferData, uint length){
    void* buffer = bufferData
    while (length > 0)
    {
      uint wrtn;
      if (!WriteFile(handle, buffer, len, out wrtn, IntPtr.Zero))
      {
         // Do some error handling
      }
      // THIS DOESNT WORK!
      // I want to move along the buffer to be able to write its remainder...
      // I tried many variations of this as well, but it seems even '+' is not valid  for a void*
      buffer += wrtn;
      len -= wrtn;
    }
}

これを見て学んだように(読み取りの対応物の使用について説明します)、バッファーの書き込み/読み取りが一度に実行されない可能性があるため、コードにwhileループを実装する必要があります。ここから問題が始まります。

バイト*がバッファーのパラメーターとして受け入れられるリンクされた読み取りの例とは異なり、void *を受け入れるようにC#メソッドの署名を保持したい場合。

これは、WriteFileを1回パスした後、まだ書き込まれていないバッファの先頭にvoid*を移動する必要があることを意味します。書き込まれたバイト数を保持するuintでvoid*をインクリメントするだけでは、どうやらこれを行うことはできません... void *には所定のサイズがないため、インクリメントできないことは理解していますが、どうすれば達成できるのでしょうか。私はやろうとしています。

4

1 に答える 1

1

bufferにキャストしてからbyte*インクリメントできるはずです。voidポインターにはサイズが関連付けられていないため、特定のバイト数を任意の方向に移動する場合は、別のタイプのポインター(さらに言えば任意のタイプ)にキャストしてから、キャストされたタイプのサイズを使用できます。ポインタ演算では、次のようになります。

buffer = (void *)((byte*)buffer + wrtn);

上記の行はbuffer、バイトポインターにキャストし、その位置wrtnをバイト数だけインクリメントしてから、新しいポインターをvoid*にキャストし直します。もちろん、byte*任意のポインタ演算を実行したい場合は、aにキャストするのが当然の選択です。

別の可能性はbuffer、すべてに沿って扱い、あなたがそれをに渡すときにbyte*のみそれをキャストすることですvoid*WriteFile

Write(IntPtr handleFile, void* bufferData, uint length)
{
    byte* buffer = (byte*)bufferData;
    while (length > 0)
    {
      uint wrtn;
      if (!WriteFile(handle, (void*)buffer, len, out wrtn, IntPtr.Zero))
      {
         // Do some error handling
      }
      buffer += wrtn;
      len -= wrtn;
    }
}

そして、最後の提案として、C#の他の呼び出し元との互換性が高くなり、その場合はより理にかなっているため、代わりにWriteを使用するように署名を完全に変更することを検討します。上記のようにを渡すときににキャストできるため、WriteFileネイティブAPIの署名と一致させることを心配する必要はありません。byte*void*byte*byte*void*

Write(IntPtr handleFile, byte* bufferData, uint length)
{
    while (length > 0)
    {
      uint wrtn;
      if (!WriteFile(handle, (void*)bufferData, len, out wrtn, IntPtr.Zero))
      {
         // Do some error handling
      }
      bufferData+= wrtn;
      len -= wrtn;
    }
}

残念ながら、私はコメント投稿者の1人に同意する必要があります。なぜあなたはこれをやっている?ストリーム指向のクラスの多くを使用して、c#でファイルの書き込みを実行するためのより良い方法があります。

于 2009-11-02T14:23:02.827 に答える