Domanda

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

Io sono l'attuazione del presente attraverso un metodo Write (..) con una firma:

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

Come ho imparato, cercando in questo (il uso della controparte di lettura viene discussa) ho bisogno di implementare un ciclo while nel mio codice, perché la scrittura / lettura del buffer potrebbe non passare attraverso in un colpo solo. Questo è dove inizia il problema:

Se voglio mantenere la mia C # firma del metodo per accettare un void *, a differenza del Leggi esempio connessi in cui un byte * viene accettato come parametro per il buffer.

Ciò significa che dopo un passaggio del WriteFile, avrei dovuto spostare la mia void * lungo l'inizio del buffer che non è stato ancora scritto. Non posso fare questo a quanto pare semplicemente incrementando void * con l'uint che contiene il numero di byte scritti ... Capisco che void * Non ha una dimensione predeterminata e che di incremento non è quindi possibile, ma mi chiedo come ho poi dovuto realizzare che cosa io sto cercando di fare.

È stato utile?

Soluzione

Si dovrebbe essere in grado di lanciare buffer ad un byte* e poi incrementarlo. Un puntatore nullo non ha dimensioni ad esso associati, quindi se si vuole mossa è un certo numero di byte in qualsiasi direzione si può lanciarlo a un diverso tipo di puntatore (qualsiasi tipo per quella materia) e quindi utilizzare le dimensioni del tipo di fuso nel aritmetica dei puntatori, in questo modo:

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

La riga precedente getta buffer a un puntatore byte, quindi incrementa la sua posizione numero wrtn di byte e quindi getta il nuovo puntatore di nuovo ad un void *. Naturalmente, lanciando ad un byte* è la scelta più ovvia, se si vogliono eseguire arbitraria aritmetica dei puntatori.

Un'altra possibilità è quella di trattare buffer come byte* tutti insieme e solo gettarlo ai void* quando si passa a 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;
    }
}

E, come ultimo suggerimento, vorrei prendere in considerazione la modifica della firma di Write del tutto di usare un byte* invece di void* perché sarebbe renderlo più compatibile con altri chiamanti da C # e un byte* ha più senso in questo caso. Non dovreste preoccuparvi di rendendolo corrisponde alla firma delle API native WriteFile dato che è possibile lanciare la byte* come indicato sopra per un void* quando passa in.

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

Ahimè, io sono d'accordo con uno dei commentatori. Perché stai facendo questo? Là sono modi migliori per realizzare un file di scrittura in C # utilizzando molte delle classi stream oriented.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top