Pergunta

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

Estou implementando isso através de um Write (..) método com uma assinatura:

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

Como eu aprendi olhando este (a uso do homólogo de leitura é discutido) Eu preciso implementar um loop while no meu código porque a leitura / gravação do buffer pode não passar de uma só vez. Este é o lugar onde o problema começar:

Se eu quero manter o meu C # assinatura método como a aceitar a * vazio, ao contrário do exemplo Leia ligada onde um byte * é aceito como um parâmetro para o buffer.

Isto significa que após um passe do WriteFile, eu deveria mudar meu void *, juntamente com o início do buffer que não tenha sido escrito ainda. Eu não posso, aparentemente, fazer isso por apenas incrementar void * com o uint que contém o número de bytes escritos ... Eu entendo que void * não tem um tamanho pré-determinado e que incrementação não é, portanto, possível, mas eu me pergunto como eu, em seguida, deve alcançar o que Eu estou tentando fazer.

Foi útil?

Solução

Você deve ser capaz de buffer fundido a um byte* e depois incrementá-lo. Um ponteiro nulo não tem tamanho associado com ele, então se você quiser movimento que um determinado número de bytes em qualquer direção que você pode lançá-lo para um tipo diferente de ponteiro (qualquer tipo para que o assunto) e, em seguida, usar o tamanho do tipo fundido na aritmética de ponteiro, assim:

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

A linha de cima moldes buffer para um byte ponteiro, em seguida, incrementa a sua posição por número wrtn de bytes e, em seguida, molda o apontador novo de volta para uma * vazio. Claro, lançando a um byte* é a escolha óbvia se você está querendo para executar a aritmética de ponteiro arbitrário.

Outra possibilidade é buffer deleite como um byte* o tempo todo e só lançá-lo aos void* quando você passá-lo para 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, como uma última sugestão, eu consideraria mudar a assinatura do Write completamente para usar um byte* vez de void* porque iria torná-lo mais compatível com outras chamadas de C # e um byte* faz mais sentido nesse caso. Você não deveria ter que se preocupar em fazer-lo coincidir com a assinatura da API nativa WriteFile desde que você pode lançar o byte* como mostrado acima para uma void* ao passar-lo.

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

Infelizmente, eu tenho que concordar com um dos comentadores. Por que você está fazendo isso? Lá são melhores maneiras de realizar uma gravação de arquivo em c #, usando muitas das classes fluxo orientado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top