Pergunta

Para o propósito de aprender Recentemente, olhou para uma montagem existente (com refletor) que utiliza Win32 WriteFile. A implementação é:

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 does not compile, because of the cast but also simply because void* does not have += operators (it is unknown size).
  buffer += (void*)wrtn;
  len -= wrtn;
}

}

É realmente as últimas 2 linhas que são problemáticos ... Por um lado, o compilador reclama que você não pode lançar uint para void *. Além disso, ele simplesmente não é possível usar + = ou mesmo + em void *, porque não é de tamanho conhecido.

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
      }
      // This works! I can add to a byte*
      buffer = buffer + wrtn; // I could also have used buffer += wrtn
      len -= wrtn;
    }
}

O código acima não funciona, mas ainda as últimas linhas irá compilar a:

buffer += (byte*)wrtn;

Eu não entendo por que e muito gostaria de saber por que se comporta compilador desta forma:

  1. Por que gerar o elenco como este (e por que não é aceito para fazer isso no código escrito pelo usuário)?
  2. O que se passa com as + = operadores em void * no primeiro exemplo? O código de código original geraram tampão + = (void *) wrtn onde tampão também é void * ????
Foi útil?

Solução

Bem para o seu segundo ponto, void * não tem informações de tamanho para que o compilador não sabe o quanto a incrementar o ponteiro por. Deve incrementar por sizeof (double)? Apenas com informações do tipo ele sabe o que esperar.

Edit: Na verdade isso se aplica ao seu primeiro ponto também. O compilador precisa saber o tamanho do tipo de dados o seu incremento. Void * não tem informações de tamanho presente de modo lançando a um byte * você deixar o compilador sabe que ele precisa para incrementar o ponteiro por sizeof (byte) * wrtn.

Edit2: Com seu esclarecimento, parece que você está perguntando por que o código do refletor emite como um * vazio em vez de como ele está escalado adequadamente Tipo (byte *). Muito provavelmente, isso deve-se ao tipo de informação a ser extraída do tipo de parâmetro e um pouco ingènua a ser utilizado no método. Este é provavelmente um problema com refletor mais do que o compilador.

Também é possível que este código ponteiro perde-lo de informações de tipo no IL, eu não testei ainda, mas não pode transportar informações de digitação (além do tamanho dos dados) para o IL para o refletor para adequadamente emitem ( 'segura' normal IL deve ter sempre esta informação tipo). Se este foi o caso do refletor pode padrão para * nula ou o tipo inferido mais próximo.

Outras dicas

Para o propósito de aprender Recentemente, olhou para uma montagem existente (com refletor)

O único problema aqui é com refletor - aparentemente, não é tão bom em deduzir o código original C # da IL. A IL si é correta, e não tem elencos (nenhum são necessários - no IL, você empurra um ponteiro e um argumento inteiro na pilha, e fazer um add / subtrair). Refletor é errado.

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